如何在Django QuerySet中生成含值列表的分组注解字段?
Django按分组聚合字段为列表的查询方案
需求:从Offer模型中按partner字段分组,将每个分组对应的所有partner_id聚合为列表,最终得到结构类似{'partner': 'xex', 'partner_ids': ['x_999', 'x_888']}的QuerySet。
方案一:数据库层面聚合(PostgreSQL专属)
如果项目使用PostgreSQL数据库,可直接利用Django提供的ArrayAgg聚合函数实现,效率更高:
- 导入聚合函数:
from django.contrib.postgres.aggregates import ArrayAgg
- 执行查询:
queryset = Offer.objects.values('partner').annotate(partner_ids=ArrayAgg('partner_id')).order_by('partner')
执行后,queryset中的每个元素即为目标字典结构,所有聚合操作在数据库端完成,避免内存加载大量数据。
方案二:Python层面分组处理(兼容所有数据库)
若使用MySQL、SQLite等不支持数组聚合的数据库,可在Python代码中通过分组处理实现:
import itertools from operator import itemgetter # 先按partner排序,确保groupby能正确分组 offers = Offer.objects.values('partner', 'partner_id').order_by('partner') result = [] for partner, group in itertools.groupby(offers, key=itemgetter('partner')): partner_ids = [item['partner_id'] for item in group] result.append({'partner': partner, 'partner_ids': partner_ids})
注意:此方法会将所有匹配记录加载到内存,数据量较大时性能不如数据库层面聚合。
补充说明
你之前尝试的annotations未成功,是因为默认聚合函数(如Count)仅做统计,而非聚合为列表;distinct('partner')仅实现去重,不会关联聚合对应的partner_id数据。
内容的提问来源于stack exchange,提问作者john-doe
相关产品推荐
相关产品推荐

