在 Django 中有一种方法可以聚合与相关对象上的条件的关系

Posted

技术标签:

【中文标题】在 Django 中有一种方法可以聚合与相关对象上的条件的关系【英文标题】:In Django is there a way to aggregate over relationships with a condition on the related object 【发布时间】:2012-08-19 15:08:27 【问题描述】:

Django 聚合文档给出了这个示例,该示例计算与每个 Publisher 相关的 Books 的数量,并返回一个查询集,其中前 5 位出版商标注了他们的图书数量(比如附加一个带有这个数量的新字段) :

>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
1323

但我只需要计算一种特定类型的书。类似的东西。

>>> pubs = Publisher.objects.annotate(num_books=Count('book__type="nonfiction"')).order_by('-num_books')[:5]

我是否可以使用过滤器来完成此操作,或者我是否需要使用原始 SQL?

以上是类似于我的实际问题的文档示例,即当系统和医院都被建模为医疗保健Entitys 时,通过系统中的医院数量来识别和量化最大的医疗组:

>>> biggest_systems = Entity.objects.filter(relationships__type_id=NAME_TO_TYPE_ID.get('hospital')).annotate(num_hospitals=Count('relationships')).order_by('-num_hospitals')[:5]
>>> biggest_systems[0].num_hospitals
25

relationships 是一个实体 M2M 字段,带有一个直通表,type_id 也是一个实体内的字段:

class Entity(models.Model):
    id = models.AutoField(verbose_name='ID',primary_key=True, db_column='ID') 
    type_id = models.IntegerField(verbose_name='detailed type',db_column='TypeID', blank=True, editable=True, choices=ENTITYTYPE_CHOICES, help_text="A category for this healthcare entity.")
    relationships = models.ManyToManyField('self', verbose_name='affiliated with', through='EntityRelationship', symmetrical=False, related_name='related_to+')

【问题讨论】:

【参考方案1】:

见Order of annotate() and filter() clauses:

Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))

或者在你的情况下:

Publisher.objects.filter(book__type='nonfiction').annotate(num_books=Count('book'))

【讨论】:

哇。可以这么简单吗?现在检查。 是的,我也印象深刻,首先我认为这会过滤出版商至少有一本“非小说”类型的书。所以我试了一下(是的,我真的试过了,我想至少我会想出一些 ORM 巫术技巧......)它确实过滤了注释的书籍类型......很好的问题,很高兴知道,赞成问题 B) 我的 num_books 对于所有通过过滤器的结果都等于 1,但我的“真实”示例有点复杂——使用带有字段(属性)的表的自引用 M2M through(关系中介)表。在我加倍确定(通过尝试文档示例)没有某些 Voodo 不能产生我们期望的结果之前,不想接受您的回答。 你能发布你的实际模型和一些数据吗? (./manage.py dumpdata yourapp.yourmodel1 yourapp.yourmodel2 etc ...) 谢谢! 威尔科。刚刚检查过,你是对的,它工作得很好,甚至形成了我更复杂的例子。如果我可以加倍投票,我会的。我最初的错误是将列表中的前几家出版商按升序而不是降序排序。我正在寻找最大的非小说出版商而不是最小的(根据文档示例)。将发布我的真实示例,根据系统中的医院数量寻找最大的医疗集团。

以上是关于在 Django 中有一种方法可以聚合与相关对象上的条件的关系的主要内容,如果未能解决你的问题,请参考以下文章

Django迁移RunPython无法调用模型方法

Django Max DateTime 聚合

Django对相关一对多对象的聚合查询

Django/Postgres:在 RangeField 上聚合

Django 聚合与查询集API

Django在数据库中找到最旧的条目