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')不是模型上的字段。
  • 我调查了一个自定义聚合字段,合并Sumcardinality,但看起来......很脆弱。
  • 我在文档中发现__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'))