我有这个模型:
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
字段上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'))
关于python - Django查询以求和ArrayFields的长度,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45180772/