python - Django 查询对 ArrayFields 的长度求和

标签 python django django-queryset django-aggregation django-annotate

我有这个模型:

class Interaction(models.Model):
    user = models.ForeignKey(User)
    codes = ArrayField(models.CharField(choices=CODE_CHOICES))

我正在尝试弄清楚如何在 Django 中执行与此 SQL 查询等效的操作:

select user_id, sum(cardinality(codes)) from interaction group by user_id;
  • 我尝试了extra(select={codes_len':'cardinality(codes)'}),但是你 无法在额外字段上注释聚合
  • 我尝试了 annotate(Sum("cardinality('codes')")),但是 cardinality('codes') 不是模型上的字段。
  • 我研究了编写一个结合 Sum 的自定义聚合字段 和基数,但这看起来……很脆弱。
  • 我在文档中发现 __len 确实可以在 ArrayField,但不在以下上下文中 注释(Sum('codes__len'))
  • 我排除了原始 SQL,因为有很多 WHERE 语句(此处省略),这使得此查询难以手动重建。

此时我认为我别无选择,只能向模型添加一个字段,该字段是 codes 字段的长度,并使用 save() 来保持同步。

真的没有别的办法了吗?我错过了什么吗?

最佳答案

事实证明,自定义聚合函数才是正确的选择!

具有以下内容:

from django.db.models import Aggregate

class SumCardinality(Aggregate):
    template = 'SUM(CARDINALITY(%(expressions)s))'

查询很简单:

Interaction.objects().filter(xxx).\
    values('user_id').annotate(codes_len=SumCardinality('codes'))

关于python - Django 查询对 ArrayFields 的长度求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45180772/

相关文章:

python - django queryset select_related 。 values() 重命名键

python - 在列表中查找唯一的元组(忽略顺序),同时在 python 中保留其他元组的原始顺序?

python - "Connection aborted"和 "Cannot connect to proxy"

python - 将应用程序中的联系表单插入 Django 中的类 View

django - Django 是否缓存自定义标签和过滤器?

Django Rest Framework 类别和子级在一个模型中

python - 地铁 python 和 linux

python - 如何将列表的列表更改为字典的字典?

django - 使用 django-templated-email 时更改主题

sql - ManyToManyField 中 Django 中对象子集的不同值