Django的查询总和ArrayFields
问题描述:
长度我有这样的模式:Django的查询总和ArrayFields
class Interaction(models.Model):
user = models.ForeignKey(User)
codes = ArrayField(models.CharField(choices=CODE_CHOICES))
,我试图找出如何做到这一点的SQL查询在Django相当于:
select user_id, sum(cardinality(codes)) from interaction group by user_id;
- 我试过
extra(select={codes_len':'cardinality(codes)'})
,但是您的 不能在或aggregate
以上的extra
字段中。 - 我试过
annotate(Sum("cardinality('codes')"))
,但是cardinality('codes')
不是模型上的字段。 - 我调查了一个自定义聚合字段,合并
Sum
和cardinality
,但看起来......很脆弱。 - 我在文档中发现
__len
确实在ArrayField
上正常工作,但在annotate(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'))