1

我有这个模型:

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)'}),但你不能annotateaggregate超过一个extra领域。
  • 我试过了annotate(Sum("cardinality('codes')")),但 cardinality('codes')不是模型上的一个字段。
  • 我研究了编写一个自定义聚合字段,它结合了Sumcardinality,但看起来……很脆弱。
  • 我在文档中发现__len确实可以在 上正常工作 ArrayField,但在 annotate(Sum('codes__len')).
  • 我排除了原始 SQL,因为有很多WHERE语句(这里省略)使得这个查询难以手动重建。

在这一点上,我想我别无选择,只能在模型中添加一个字段长度的codes字段并弄乱以save()使其保持同步。

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

4

1 回答 1

2

事实证明,自定义聚合函数是要走的路!

具有以下内容:

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'))
于 2017-08-09T00:45:27.053 回答