Jen*_*Alm 15 django aggregate-functions django-models django-queryset
我正在Django建立一个食物记录数据库,我有一个查询相关的问题.
我已经建立了我的模型,以包括(除其他外)通过消费模型通过M2M字段"消费者"连接到用户模型的食品模型.食物模型描述了食物菜肴,消费模型描述了用户对食物的消费(日期,数量等).
class Food(models.Model):
food_name = models.CharField(max_length=30)
consumer = models.ManyToManyField("User", through=Consumption)
class Consumption(models.Model):
food = models.ForeignKey("Food")
user = models.ForeignKey("User")
Run Code Online (Sandbox Code Playgroud)
我想创建一个查询,返回按Food对象出现在该用户的消耗表中的次数排序的所有Food对象(用户食用食物的次数).
我正在尝试以下方面:
Food.objects.all().annotate(consumption_times = Count(consumer)).order_by('consumption_times')`
Run Code Online (Sandbox Code Playgroud)
但这当然会计算与Food对象相关的所有Consumer对象,而不仅仅是与用户关联的对象.我是否需要更改模型,或者我只是遗漏了查询中明显的内容?
这是一个非常关键的时间操作(除此之外,它用于填充前端的自动完成字段)和Food表有几千个条目,所以我宁愿在数据库端进行排序,而不是做蛮力方法并迭代结果做:
Consumption.objects.filter(food=food, user=user).count()
Run Code Online (Sandbox Code Playgroud)
然后使用python排序对它们进行排序.我不认为随着用户群的增加,这种方法会扩展得很好,我想从头开始设计数据库作为未来的证据.
有任何想法吗?
Smi*_*ris 24
也许是这样的?
Food.objects.filter(consumer__user=user)\
.annotate(consumption_times=Count('consumer'))\
.order_by('consumption_times')
Run Code Online (Sandbox Code Playgroud)
spa*_*kyb 20
我有一个非常类似的问题.基本上,我知道你想要的SQL查询是:
SELECT food.*, COUNT(IF(consumption.user_id=123,TRUE,NULL)) AS consumption_times
FROM food LEFT JOIN consumption ON (food.id=consumption.food_id)
ORDER BY consumption_times;
Run Code Online (Sandbox Code Playgroud)
我希望你可以混合聚合函数和F表达式,注释没有聚合函数的F表达式,为F表达式提供更丰富的操作/函数,并且具有基本上是自动F表达式注释的虚拟字段.这样你就可以做到:
Food.objects.annotate(consumption_times=Count(If(F('consumer')==user,True,None)))\
.order_by('consumtion_times')
Run Code Online (Sandbox Code Playgroud)
此外,只是能够更容易地添加自己的复杂聚合函数会很好,但与此同时,这是一个增加聚合函数来执行此操作的hack.
from django.db.models import aggregates,sql
class CountIf(sql.aggregates.Count):
sql_template = '%(function)s(IF(%(field)s=%(equals)s,TRUE,NULL))'
sql.aggregates.CountIf = CountIf
consumption_times = aggregates.Count('consumer',equals=user.id)
consumption_times.name = 'CountIf'
rows = Food.objects.annotate(consumption_times=consumption_times)\
.order_by('consumption_times')
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
13517 次 |
最近记录: |