我建立在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")
我想创建一个返回由食品对象出现在消费表用户(次用户消费的食品数量)的次数下令所有食品对象的查询。
我想在行的内容:
Food.objects.all().annotate(consumption_times = Count(consumer)).order_by('consumption_times')`
但是,这当然算有关食品对象的所有消费对象,不只是与用户相关联的人。 我需要改变我的模型或我只思念的东西查询明显?
这是一个漂亮的时间要求严格的操作(除其他事项外,它被用来填补在前端的自动完成场)和食物表有几千项,所以我宁愿做排序在数据库端,而不是做蛮力方法和遍历结果做:
Consumption.objects.filter(food=food, user=user).count()
然后使用Python排序对它们进行排序。 我不认为这方法将很好地进行缩放随着用户基数增大,我想数据库,我可以从一开始就设计为面向未来。
有任何想法吗?
也许这样的事情?
Food.objects.filter(consumer__user=user)\
.annotate(consumption_times=Count('consumer'))\
.order_by('consumption_times')
我有一个非常类似的问题。 基本上,我知道你想要的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;
我希望的是,你可以混合聚合函数和F表达,诠释˚F表情没有聚合函数,具有更丰富的适用于F表达操作/功能,并且具有基本上自动˚F表达式标注虚拟领域。 所以,你可以这样做:
Food.objects.annotate(consumption_times=Count(If(F('consumer')==user,True,None)))\
.order_by('consumtion_times')
此外,仅仅能够能够更容易地添加自己的复杂的聚合函数将是很好的,但在此期间,这里是增加了集合函数来做到这一点黑客攻击。
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')