当前位置:  开发笔记 > 编程语言 > 正文

过滤Django ORM中的Aggregate

如何解决《过滤DjangoORM中的Aggregate》经验,为你挑选了1个好方法。

我有一个看起来像这样的函数:

def post_count(self):
        return self.thread_set.aggregate(num_posts=Count('post'))['num_posts']

我只想计算状态标记为"有效"的帖子.有一种简单的方法可以在Count函数之前添加过滤器吗?

型号定义:

class Category(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100, blank=True, primary_key=True)
    ordering = models.IntegerField(max_length=3, default=0)

    @property
    def thread_count(self):
        return self.thread_set.all().count()

    @property
    def post_count(self):
        return self.thread_set.aggregate(num_posts=Count('post'))['num_posts']

class Thread(models.Model):
    user = models.ForeignKey(User)
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100)
    content = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    latest_activity = models.DateTimeField(auto_now_add=True)

class Post(models.Model):
    thread = models.ForeignKey(Thread)
    parent = models.ForeignKey('Post', null=True, blank=True)
    display_name = models.CharField(max_length=100)
    email = models.EmailField(db_index=True)
    ip_address = models.IPAddressField(null=True, blank=True)
    content = models.TextField()
    status = models.CharField(choices=STATUS_CHOICES, max_length=25, db_index=True, default='approved')
    created = models.DateTimeField()

Michał Marcz.. 10

好的,既然问题包括模型定义,我向你提出这应该有用,除非你的Django版本不支持我在这里使用的某些功能(在这种情况下,请告诉我!):

Post.objects.filter(thread__in=thread_set, status='active').aggregate(num_posts=Count('id'))

Django允许__in过滤器使用QuerySet来决定IN子句在SQL中应该是什么样子,所以如果你通过thread__in=thread_set,Django将过滤帖子,以便只有那些thread字段指向你的一个id线程中的那些thread_set保留用于aggregate调用看到.

这应该使用一个类似于WHERE thread_id IN ...内部的db查询过滤帖子,而不是每个线程一个查询,这确实是可怕的.如果发生任何其他事情,这将是Django中的一个错误......

结果应该是最多两个查询来建立一个Category帐户 - 一个用于获取thread_set,另一个用于实际计算帖子.另一种方法是有一个线程/后加入要过滤的基础上ThreadcategoryPoststatus场,我不一定会想到会快很多.(我说'最多',因为我猜他们可以自动融合......虽然我不认为这会发生在当前的Django上.无法检查ATM,对不起.)

编辑: Django的QuerySet API参考说明__in过滤器:


在给定的列表中.

例:

Entry.objects.filter(id__in=[1, 3, 4])

SQL等价物:

SELECT ... WHERE id IN (1, 3, 4);

您还可以使用查询集动态评估值列表,而不是提供文字值列表:

inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)

此查询集将作为subselect语句进行评估:

SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

上面的代码片段也可以写成如下:

inner_q = Blog.objects.filter(name__contains='Cheddar').values('pk').query
entries = Entry.objects.filter(blog__in=inner_q)

在Django 1.1中更改:在Django 1.0中,只有后一段代码有效.

第二种形式的可读性和不自然性,因为它访问内部查询属性并需要一个ValuesQuerySet.如果您的代码不需要与Django 1.0兼容,请使用第一个表单,直接传入查询集.


所以,我想Django的能够通过的一个单一的查询这里的问题的情况下的分贝.如果db的查询分析器做得很好,效果可能非常接近最佳.:-)



1> Michał Marcz..:

好的,既然问题包括模型定义,我向你提出这应该有用,除非你的Django版本不支持我在这里使用的某些功能(在这种情况下,请告诉我!):

Post.objects.filter(thread__in=thread_set, status='active').aggregate(num_posts=Count('id'))

Django允许__in过滤器使用QuerySet来决定IN子句在SQL中应该是什么样子,所以如果你通过thread__in=thread_set,Django将过滤帖子,以便只有那些thread字段指向你的一个id线程中的那些thread_set保留用于aggregate调用看到.

这应该使用一个类似于WHERE thread_id IN ...内部的db查询过滤帖子,而不是每个线程一个查询,这确实是可怕的.如果发生任何其他事情,这将是Django中的一个错误......

结果应该是最多两个查询来建立一个Category帐户 - 一个用于获取thread_set,另一个用于实际计算帖子.另一种方法是有一个线程/后加入要过滤的基础上ThreadcategoryPoststatus场,我不一定会想到会快很多.(我说'最多',因为我猜他们可以自动融合......虽然我不认为这会发生在当前的Django上.无法检查ATM,对不起.)

编辑: Django的QuerySet API参考说明__in过滤器:


在给定的列表中.

例:

Entry.objects.filter(id__in=[1, 3, 4])

SQL等价物:

SELECT ... WHERE id IN (1, 3, 4);

您还可以使用查询集动态评估值列表,而不是提供文字值列表:

inner_qs = Blog.objects.filter(name__contains='Cheddar')
entries = Entry.objects.filter(blog__in=inner_qs)

此查询集将作为subselect语句进行评估:

SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

上面的代码片段也可以写成如下:

inner_q = Blog.objects.filter(name__contains='Cheddar').values('pk').query
entries = Entry.objects.filter(blog__in=inner_q)

在Django 1.1中更改:在Django 1.0中,只有后一段代码有效.

第二种形式的可读性和不自然性,因为它访问内部查询属性并需要一个ValuesQuerySet.如果您的代码不需要与Django 1.0兼容,请使用第一个表单,直接传入查询集.


所以,我想Django的能够通过的一个单一的查询这里的问题的情况下的分贝.如果db的查询分析器做得很好,效果可能非常接近最佳.:-)

推荐阅读
乐韵答题
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有