gpt4 book ai didi

python - Django 中的复杂聚合

转载 作者:行者123 更新时间:2023-11-30 22:38:18 25 4
gpt4 key购买 nike

使用 Django Rest Framework 3.x 和 Django 1.1.10 。我有一个代表用户的模型。当我通过访问 /users/ 列出所有用户时DRF 中的端点列表必须包含更多通过另一个模型(称为所有者)与用户相关的数据。每个项目都有一个所有者,所有者有用户。

我在 User 模型上创建了一个额外的属性,它只返回数据的 JSON 数组。这是我无法改变的,因为这是对前端的要求。我必须返回与每个用户相关的项目总数,并且需要执行三种不同的计数来获取数据。

我需要在同一模型上获取多个 count() 的项目,但条件不同。

单独执行这些操作很容易,其中两个很简单,最后一个则更复杂:

Item.objects.filter(owner__user=self).count()
Item.objects.filter(owner__user=self, published=True).count()
Item.objects.filter(Q(history__action__name='argle') | Q(history__action__name='bargle'),
history__since__lte=now,
history__until__gte=now,
owner__user=self).count()

问题是因为这是为每个用户运行的,而且用户数量很多。最终,这会生成超过 300 个数据库查询,我希望将这些查询降至最低。

到目前为止我已经想出了这个:

Item.objects.filter(owner__user=self)\
.aggregate(published=Count('published'),
total=Count('id'))

这将聚合前两个计数,返回它们,并且只返回一个 SELECT将在数据库上执行。有没有办法合并最后一个count()调用同样的aggregate()

我尝试了很多事情,但似乎不可能。我应该写一个自定义SELECT并使用Item.objects.raw()

我还注意到执行 aggregate()最后一个count()在我的开发机器和 SQLite 上比在带有 Postgresql 的临时服务器上更快,这有点奇怪,但这不是我现在主要关心的问题。

最佳答案

由于您需要查询集中每个项目的计数,因此您应该使用 annotate这将只执行 1 个查询,而不是聚合。

根据条件对相关对象进行计数的最佳方法是使用 conditional aggregation

User.objects.annotate(
total_items=Count('items'),
published=Sum(Case(When(items__published=True, then=1), output_field=IntegerField())),
foo=Sum(Case(When(
Q(history__action__name='argle') | Q(history__action__name='bargle'),
history__since__lte=now,
history__until__gte=now,
then=1
), output_field=IntegerField()))
)

关于python - Django 中的复杂聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43628390/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com