限制每组 n 个结果 - Django 查询集

Posted

技术标签:

【中文标题】限制每组 n 个结果 - Django 查询集【英文标题】:limit n results per group by - Django queryset 【发布时间】:2017-10-13 14:55:42 【问题描述】:

我正在尝试创建一个查询,我可以在其中提取屏幕上显示的每个类别的最后 3 个论坛帖子。这是我的模型的设置方式:

class ForumCategory(models.Model):
    name = models.CharField(max_length=40)
    description = models.TextField()
    class_id = models.ForeignKey(Class)


class ForumPost(models.Model):
    name = models.CharField(max_length=100)
    details = models.TextField()
    author = models.ForeignKey(User)
    class_id = models.ForeignKey(Class)
    category = models.ForeignKey(ForumCategory)
    created_at = models.DateTimeField(auto_now_add=True)

我当前的查询一般返回 3 个最近的帖子,而不是每个类别 3 个:

categories = ForumCategory.objects.filter(class_id=class_id)
        forum_post = ForumPost.objects.filter(category_id__in=categories.values_list('id', flat=True)).order_by('-category_id')[:3]

所以我首先获取属于特定类别的所有类别,然后我想列出这些类别以及每个类别中的 3 个最新帖子。

【问题讨论】:

【参考方案1】:

正如@exprator 所说,只是一个小改动,

categories = ForumCategory.objects.filter(class_id=class_id)
result_dict = 
for cat in categories:
    forum_post = ForumPost.objects.filter(category__pk=cat.pk).order_by('-created')[:3]
    result_dict[cat.name] = forum_post

然后可以从对应的类别名称中访问每个类别的查询集。

【讨论】:

【参考方案2】:

在这种情况下,您别无选择,只能使用原始 SQL。如果您使用的是 PostgreSQL,则需要这样的东西:

SELECT * FROM (SELECT *, row_number() OVER (PARTITION BY forum_category_id)  
FROM forum_post) x WHERE x.row_number <= 3;

很遗憾,由于这张票,您现在无法在 Django ORM 中表达这一点:Provide a way to manage grouping with RawSQL

【讨论】:

我认为作者的问题假设只使用一个 SQL 请求来获取所有数据。否则,任务是微不足道的。您可以迭代类别,但这是显而易见的解决方案,它会生成太多查询(对于小型应用程序/站点来说不是问题,当您有一个高负载项目时会是大问题)。

以上是关于限制每组 n 个结果 - Django 查询集的主要内容,如果未能解决你的问题,请参考以下文章

获取每组的前 n 个结果 [重复]

Django数据操作

Django中模型

Django 数据库操作

如何使用 Django Rest 过滤器限制查询结果

如何限制从 NSMetadataQuery 返回的结果数量?