【问题标题】:django most efficient way to count same field values in a querydjango 计算查询中相同字段值的最有效方法
【发布时间】:2011-04-06 02:32:09
【问题描述】:

假设我有一个包含很多字段的模型,但我只关心一个字符字段。假设 charfield 可以是任何东西,所以我不知道可能的值,但我知道这些值经常重叠。所以我可以有 20 个带有“abc”的对象和 10 个带有“xyz”的对象,或者我可以有 50 个带有“def”的对象和 80 个带有“stu”的对象,我有 40000 个没有重叠的对象,我真的不在乎。

如何有效地计算对象?我想要返回的是这样的:

{'abc': 20, 'xyz':10, '其他': 10,000}

或类似的东西,无需进行大量 SQL 调用。

编辑:

我不知道是否有人会看到这个,因为我编辑它有点晚了,但是......

我有这个模型:

类动作(模型。模型): 作者 = models.CharField(max_length=255) purl = models.CharField(max_length=255, null=True)

从答案中,我做到了:

groups = Action.objects.filter(author='James').values('purl').annotate(count=Count('purl'))

但是……

这就是组:

{“purl”:“waka”},{“purl”:“waka”},{“purl”:“waka”},{“purl”:“waka”},{“purl”:“mora”}, {“purl”:“mora”},{“purl”:“mora”},{“purl”:“mora”},{“purl”:“mora”},{“purl”:“lora”}

(我只是用虚拟值填充 purl)

我想要的是

{'waka':4,'mora':5,'lora':1}

希望有人会看到这个编辑...

编辑 2:

显然 我的数据库(BigTable)不支持 Django 的聚合函数,这就是为什么我遇到了所有问题。

【问题讨论】:

    标签: django django-models django-queryset


    【解决方案1】:

    您想要类似于“count ... group by”的内容。您可以使用 django 的 ORM 的聚合功能来做到这一点:

    from django.db.models import Count
    
    fieldname = 'myCharField'
    MyModel.objects.values(fieldname)
        .order_by(fieldname)
        .annotate(the_count=Count(fieldname))
    

    之前关于这个主题的问题:

    【讨论】:

    • 实际上,我有这个:groups =Action.objects.filter(author= author).values('purl').annotate(count=Count('purl')) a = [each for each in groups] 但 a 仅等于其中的一堆: {"purl": "wakawaka"} 没有字典的计数键。
    • 我已经编辑了答案以解决这个问题,但以防万一它没有得到批准:如果您收到多个看起来不汇总的结果:确保您按以下方式订购查询集您希望分组的字段。
    • 感谢您的回答。这是在注释之前提到 order_by 的唯一答案,这是工作所必需的。
    • 为什么需要order_by
    • @Jarad 链接的“以前的问题”提到了它,就像文档的 this section 一样:“在选择输出数据时使用查询集的 order_by() 部分中提到的字段,即使在values() 调用中没有另外指定它们。这些额外的字段用于将“喜欢”的结果组合在一起,它们可以使原本相同的结果行看起来是分开的。尤其是在计算事物时会出现这种情况。”所以默认排序可能会添加一些无关紧要的字段来搞砸
    【解决方案2】:

    您可以在查询集上使用 Django 的 Count aggregation 来完成此操作。像这样的:

    from django.db.models import Count
    queryset = MyModel.objects.all().annotate(count = Count('my_charfield'))
    for each in queryset:
        print "%s: %s" % (each.my_charfield, each.count)
    

    【讨论】:

      【解决方案3】:

      这称为聚合,Django supports it directly

      您可以通过过滤要计算的值、获取值列表并计算它们来获得准确的输出,所有这些都在一组数据库调用中完成:

      from django.db.models import Count
      MyModel.objects.filter(myfield__in=('abc', 'xyz')).\
              values('myfield').annotate(Count('myfield'))
      

      【讨论】:

        【解决方案4】:

        除非您的字段值始终保证在特定情况下,否则在执行计数之前对其进行转换可能很有用,即“apple”和“Apple”将被视为相同。

        from django.db.models import Count
        from django.db.models.functions import Lower
        
        MyModel.objects.annotate(lower_title=Lower('title')).values('lower_title').annotate(num=Count('lower_title')).order_by('num')
        

        【讨论】:

          猜你喜欢
          • 2018-10-11
          • 2012-01-26
          • 2011-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-08-08
          相关资源
          最近更新 更多