Django的注释和聚合方法之间的区别?

Posted

技术标签:

【中文标题】Django的注释和聚合方法之间的区别?【英文标题】:Difference between Django's annotate and aggregate methods? 【发布时间】:2011-12-20 09:02:57 【问题描述】:

Django 的QuerySet 有两个方法,annotateaggregate。文档说:

与aggregate() 不同,annotate() 不是终结子句。 annotate() 子句的输出是一个 QuerySet。

它们之间还有其他区别吗?如果不是,那为什么aggregate 存在?

【问题讨论】:

【参考方案1】:

我会专注于示例查询,而不是文档中的引用。 Aggregate 计算 整个 查询集的值。 Annotate 计算查询集中每个项目的汇总值。

聚合

>>> Book.objects.aggregate(average_price=Avg('price'))
'average_price': 34.35

返回一个字典,其中包含查询集中所有本书的平均价格。

注释

>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

q 是书籍的查询集,但每本书都标注了作者的数量。

【讨论】:

我是否更正了 .annotate() 仅在 qs 上不会击中数据库,但调用 q[0].num_authors 会?我假设aggregate 必须始终命中数据库,因为它是一个终端子句? @alias51 这与原始问题确实相关,所以我认为 cmets 对一个八岁问题的提问不是最好的地方。如果要检查查询何时运行,可以check connection.queries。提示:检查是 book = q[0] 还是 `book.num_authors` 引起了查询。【参考方案2】:

聚合 在整个 QuerySet 上聚合生成结果(摘要)值。 聚合对行集进行操作以从行集中获取单个值。(例如行集中所有价格的总和)。聚合应用于整个 QuerySet 并在整个 QuerySet 上生成结果(摘要)值。

在模型中:

class Books(models.Model):
    name = models.CharField(max_length=100)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=3)

在外壳中:

>>> Books.objects.all().aggregate(Avg('price'))
# Above code will give the Average of the price Column 
>>> 'price__avg': 34.35

注释 Annotate 为 QuerySet 中的每个对象生成一个独立的摘要。(可以说它迭代 QuerySet 中的每个对象并应用操作)

在模型中:

class Video(models.Model):
    name = models.CharField(max_length=52, verbose_name='Name')
    video = models.FileField(upload_to=document_path, verbose_name='Upload 
               video')
    created_by = models.ForeignKey(User, verbose_name='Created by', 
                       related_name="create_%(class)s")
    user_likes = models.ManyToManyField(UserProfile, null=True, 
                  blank=True, help_text='User can like once', 
                         verbose_name='Like by')

在视图中:

videos = Video.objects.values('id', 'name','video').annotate(Count('user_likes',distinct=True)

它会统计每个视频的点赞数

【讨论】:

为什么在上一个例子中需要distinct=True @YuriyLeonov distinct=True 用于操作在不同值上执行。它与当前提出的问题无关。抱歉,实际上我已经在我的代码上使用了。【参考方案3】:

这是主要区别,但聚合也比注释在更大范围内起作用。注释本质上与查询集中的各个项目相关。如果您在多对多字段上运行Count 注释,您将获得查询集的每个成员的单独计数(作为添加的属性)。但是,如果您要对聚合执行相同操作,它将尝试计算查询集的 每个 成员上的每个关系,甚至是重复的,并将其作为一个值返回。

【讨论】:

我是否更正了 .annotate() 仅在 qs 上并没有命中数据库,但调用诸如 q[0].num_authors 之类的注释的结果可以吗?我假设aggregate 必须始终命中数据库,因为它是一个终端子句?

以上是关于Django的注释和聚合方法之间的区别?的主要内容,如果未能解决你的问题,请参考以下文章

复杂的 Django ORM 注释和聚合

Django中GROUP BY中注释的聚合

django的聚合函数和aggregateannotate方法使用

注释 SUM 聚合函数导致 Django 中的“无”值

有没有办法在 Django Querysets 中组合注释和过滤聚合?

django 使用基于查询的聚合值注释模型