Django 中的多查询优化
Multiple queries optimization in Django
我有三个模型,User、Achievement 和 AchievementHistory
用户模型看起来像
User(models.Model):
name = models.CharField(max_length=255)
成就模型看起来像
Achievement(models.Model):
name = models.CharField(max_length=255)
AchievementHistory 模型看起来像
AchievementHistory(models.Model):
achievement = models.ForeignKey(Achievement, on_delete=models.CASCADE)
user = models.ForeignKey(user, on_delete=models.CASCADE)
我算什么用户的每一个成就。假设存在 'hello'、'world'、'goodbye' 等三个成就,用户实现了 'hello' 两次,世界实现了三次,那么我想要这样的输出
{
'hello': 2,
'world': 3,
'goodbye': 0,
}
我可以通过以下函数找到这个
def get_user_achievements_by_id(id):
user = User.objects.get(pk=id)
response = []
for achievement in Achievement.objects.all():
number_of_entries = AchievementHistory.objects.filter(
user=user, achievement=achievement).count()
response.append({str(achievement.title): number_of_entries})
return response
这里实际上执行了三个不同的查询。有什么办法可以减少查询数量,实际上是在单个查询中。
您可以使用 annotation。像这样:
from django.db.models import Count
AchievementHistory.objects.filter(user=user).values('achievement__title').annotate(
Count('achievement__title')
).order_by()
我有三个模型,User、Achievement 和 AchievementHistory
用户模型看起来像
User(models.Model):
name = models.CharField(max_length=255)
成就模型看起来像
Achievement(models.Model):
name = models.CharField(max_length=255)
AchievementHistory 模型看起来像
AchievementHistory(models.Model):
achievement = models.ForeignKey(Achievement, on_delete=models.CASCADE)
user = models.ForeignKey(user, on_delete=models.CASCADE)
我算什么用户的每一个成就。假设存在 'hello'、'world'、'goodbye' 等三个成就,用户实现了 'hello' 两次,世界实现了三次,那么我想要这样的输出
{
'hello': 2,
'world': 3,
'goodbye': 0,
}
我可以通过以下函数找到这个
def get_user_achievements_by_id(id):
user = User.objects.get(pk=id)
response = []
for achievement in Achievement.objects.all():
number_of_entries = AchievementHistory.objects.filter(
user=user, achievement=achievement).count()
response.append({str(achievement.title): number_of_entries})
return response
这里实际上执行了三个不同的查询。有什么办法可以减少查询数量,实际上是在单个查询中。
您可以使用 annotation。像这样:
from django.db.models import Count
AchievementHistory.objects.filter(user=user).values('achievement__title').annotate(
Count('achievement__title')
).order_by()