Django查询(聚合和计数)
嘿,伙计们,我有一个这样的模型:Django查询(聚合和计数),django,django-models,django-orm,django-piston,Django,Django Models,Django Orm,Django Piston,嘿,伙计们,我有一个这样的模型: class Interaction(DateAwareModel, UserAwareModel): page = models.ForeignKey(Page) container = models.ForeignKey(Container, blank=True, null=True) content = models.ForeignKey(Content) interaction_node = models.ForeignKey(Inter
class Interaction(DateAwareModel, UserAwareModel):
page = models.ForeignKey(Page)
container = models.ForeignKey(Container, blank=True, null=True)
content = models.ForeignKey(Content)
interaction_node = models.ForeignKey(InteractionNode)
kind = models.CharField(max_length=3, choices=INTERACTION_TYPES)
"data": {
"container 1": {
"tag_count": 3,
"com_count": 1
},
"container 2": {
"tag_count": 7,
"com_count": 12
},
...
}
SELECT container_id, kind, count(*) FROM rb_interaction GROUP BY container_id, kind;
我希望能够执行一个查询,以获得按容器分组的交互数量,然后再按种类分组。其想法是输出JSON数据结构(由活塞负责序列化)如下所示:
class Interaction(DateAwareModel, UserAwareModel):
page = models.ForeignKey(Page)
container = models.ForeignKey(Container, blank=True, null=True)
content = models.ForeignKey(Content)
interaction_node = models.ForeignKey(InteractionNode)
kind = models.CharField(max_length=3, choices=INTERACTION_TYPES)
"data": {
"container 1": {
"tag_count": 3,
"com_count": 1
},
"container 2": {
"tag_count": 7,
"com_count": 12
},
...
}
SELECT container_id, kind, count(*) FROM rb_interaction GROUP BY container_id, kind;
SQL将如下所示:
class Interaction(DateAwareModel, UserAwareModel):
page = models.ForeignKey(Page)
container = models.ForeignKey(Container, blank=True, null=True)
content = models.ForeignKey(Content)
interaction_node = models.ForeignKey(InteractionNode)
kind = models.CharField(max_length=3, choices=INTERACTION_TYPES)
"data": {
"container 1": {
"tag_count": 3,
"com_count": 1
},
"container 2": {
"tag_count": 7,
"com_count": 12
},
...
}
SELECT container_id, kind, count(*) FROM rb_interaction GROUP BY container_id, kind;
关于如何使用ORM按多个字段分组有什么想法吗?(如果可以避免id,我不想为此项目编写原始查询)这似乎是一个简单而常见的查询
在您提问之前:我已经看过django聚合文档和原始查询文档
更新
根据以下建议,我创建了一个自定义管理器来处理此问题:
class ContainerManager(models.Manager):
def get_query_set(self, *args, **kwargs):
qs = super(ContainerManager, self).get_query_set(*args, **kwargs)
qs.filter(Q(interaction__kind='tag') | Q(interaction__kind='com')).distinct()
annotations = {
'tag_count':models.Count('interaction__kind'),
'com_count':models.Count('interaction__kind')
}
return qs.annotate(**annotations)
这仅统计标签或com类型的交互,而不是通过group by检索标签和com的计数。很明显,从代码中可以看出它是这样工作的,但不知道如何修复它…创建一个自定义管理器:
class ContainerManager(models.Manager):
def get_query_set(self, *args, **kwargs):
qs = super(ContainerManager, self).get_query_set(*args, **kwargs)
annotations = {'tag_count':models.Count('tag'), 'com_count':models.Count('com')}
return qs.annotate(**annotations)
class Container(models.Model):
...
objects = ContainerManager()
然后,Container
查询将始终包括tag\u count
和com\u count
属性。您可能需要修改注释,因为我没有模型的副本可供参考;我只是猜到了字段名
更新:
因此,在对模型有了更好的理解之后,注释将无法满足您的需求。实际上,要获得“tag”或“com”的容器的种类的计数,唯一的方法是:
tag_count = Container.objects.filter(kind='tag').count()
com_count = Container.objects.filter(kind='com').count()
注释不会提供这些信息。我认为可以编写自己的聚合和注释,因此这可能是一个可行的解决方案。然而,我自己从来没有这样做过,所以我真的不能给你任何指导。您可能一直在使用直接SQL。响应非常好,但我主要关心的是:我希望能够在数据库中完成聚合工作,而不是迭代容器。我可能错了,但这似乎会计算每个容器的标记和注释(隐含循环),而使用GROUPBY子句会更好地使用DB引擎。思想?没有迭代<代码>注释
与过滤器
和queryset API的其余部分类似。它只是将内容附加到最终将发送到DB的SQL中。只有一个查询。Kind实际上在我的交互模型上,如果我想在“interaction\uuuu Kind”=“tag”或“com”中注释count,您介意提到您将如何做吗?只需在之前插入.filter(Q(interaction\uu Kind='tag')| Q(interaction\uu Kind='com')).distinct()
Q
位于django.db.models
中。是的,根据您的更新,它不起作用。我写这个答案是基于这样一个假设,即tag
和com
是“可数的”,即外键。我将更新上面的答案,但您可能不会喜欢;)。