Django 查询求和 ArrayFields 的长度
Posted
技术标签:
【中文标题】Django 查询求和 ArrayFields 的长度【英文标题】:Django query to Sum the lengths of ArrayFields 【发布时间】:2017-12-24 03:32:25 【问题描述】:我有这个模型:
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)')
,但是你
不能在extra
字段上使用annotate
或aggregate
。
我试过annotate(Sum("cardinality('codes')"))
,但是
cardinality('codes')
不是模型上的字段。
我研究了编写一个自定义聚合字段,它结合了Sum
和cardinality
,但看起来……很脆弱。
我在文档中发现 __len
在
ArrayField
,但不在上下文中
annotate(Sum('codes__len'))
。
我排除了原始 SQL,因为有很多 WHERE
语句(此处省略)使得该查询难以手动重构。
此时我想我别无选择,只能在模型中添加一个字段,即codes
字段的长度并与save()
混淆以保持同步。
真的没有别的办法了吗?我错过了什么吗?
【问题讨论】:
【参考方案1】:事实证明,自定义聚合函数是要走的路!
以下内容:
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'))
【讨论】:
以上是关于Django 查询求和 ArrayFields 的长度的主要内容,如果未能解决你的问题,请参考以下文章