Django ORM:按列表中的值过滤结果,限制每个值的答案?
Django ORM: Filter results by values from list, limit answers per value?
我正在使用 Django 2.0 并且有一个带有 ForeignKey(User, ...) 的内容模型。我还有一个用户 ID 列表,我想为其获取该内容,按 "newest first" 排序,但每个用户最多只能有 25 个元素。我知道我可以做到:
Content.objects.filter(user_id__in=[1, 2, 3, ...]).order_by('-id')
...获取每个用户创建的所有 Content 对象,此外,我将首先使用最新元素对其进行排序。但我想为每个用户获取最多 25 个元素(有些用户可能创建数百个这样的对象,有些可能创建零个)。当然还有笨办法:
for user in [1, 2, 3, ...]:
Content.objects.filter(user_id=user).order_by('-id')[:25]
然而,这与用户 ID 列表中的对象一样多地访问数据库,而且数量相当多(每个页面视图大约 100 次左右)。有什么办法可以优化这种情况吗? (我试过环顾四周 select_related
,但这似乎能找到尽可能多的相关模型。)
有很多方法可以形成 greatest-n-per-group 查询,但在这种情况下,您可以形成所有用户的前 n 个查询的并集:
contents = Content.objects.\
none().\
union(*[Content.objects.
filter(user_id=uid).
order_by('-id')[:25] for uid in user_ids],
all=True)
然后使用 prefetch_related()
,您可以生成一个查询集来获取用户并注入最新内容的属性:
users = User.objects.\
filter(id__in=user_ids).\
prefetch_related(models.Prefetch(
'content_set',
queryset=contents,
to_attr='latest_content'))
它真的多次访问数据库吗?我没有看过原始 SQL 但根据文档,它等同于 LIMIT
子句并且它还声明 "Generally, slicing a QuerySet returns a new QuerySet – it doesn’t evaluate the query".
https://docs.djangoproject.com/en/2.0/topics/db/queries/#limiting-querysets
我很想看看原始的 SQL 如果你正在看它并且它不会这样做,因为我使用这个范例。
我正在使用 Django 2.0 并且有一个带有 ForeignKey(User, ...) 的内容模型。我还有一个用户 ID 列表,我想为其获取该内容,按 "newest first" 排序,但每个用户最多只能有 25 个元素。我知道我可以做到:
Content.objects.filter(user_id__in=[1, 2, 3, ...]).order_by('-id')
...获取每个用户创建的所有 Content 对象,此外,我将首先使用最新元素对其进行排序。但我想为每个用户获取最多 25 个元素(有些用户可能创建数百个这样的对象,有些可能创建零个)。当然还有笨办法:
for user in [1, 2, 3, ...]:
Content.objects.filter(user_id=user).order_by('-id')[:25]
然而,这与用户 ID 列表中的对象一样多地访问数据库,而且数量相当多(每个页面视图大约 100 次左右)。有什么办法可以优化这种情况吗? (我试过环顾四周 select_related
,但这似乎能找到尽可能多的相关模型。)
有很多方法可以形成 greatest-n-per-group 查询,但在这种情况下,您可以形成所有用户的前 n 个查询的并集:
contents = Content.objects.\
none().\
union(*[Content.objects.
filter(user_id=uid).
order_by('-id')[:25] for uid in user_ids],
all=True)
然后使用 prefetch_related()
,您可以生成一个查询集来获取用户并注入最新内容的属性:
users = User.objects.\
filter(id__in=user_ids).\
prefetch_related(models.Prefetch(
'content_set',
queryset=contents,
to_attr='latest_content'))
它真的多次访问数据库吗?我没有看过原始 SQL 但根据文档,它等同于 LIMIT
子句并且它还声明 "Generally, slicing a QuerySet returns a new QuerySet – it doesn’t evaluate the query".
https://docs.djangoproject.com/en/2.0/topics/db/queries/#limiting-querysets
我很想看看原始的 SQL 如果你正在看它并且它不会这样做,因为我使用这个范例。