我有这个模型:

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字段上aggregateextra
我尝试了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/

10-09 07:25