You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中统计JSONField内对象列表数量的问题

解决Django中统计JSONField数组元素数量的问题

问题描述

我刚接触Django的高级查询,遇到了一个统计JSONField数组长度的问题:

我定义了这样的模型:

class TopCountries(models.Model):
    top_countries = JSONField(null=True)

其中top_countries存储的是一个国家列表的JSON数组,结构如下:

'top_countries': [
    {'country_code': 'AX', 'country_name': 'Åland Islands'},
    {'country_code': 'AL', 'country_name': 'Albania'},
    {'country_code': 'DZ', 'country_name': 'Algeria'}
]

我尝试用下面的查询统计数组里的元素数量:

TopCountries.objects.aggregate(Count('top_countries'))

但实际得到的输出是{'top_countries__count': 1},而我期望的是{'top_countries__count': 3},请问该怎么解决?


问题原因

你用的Count('top_countries')其实是在统计数据库表中top_countries字段不为空的记录行数,而不是JSON数组内部的元素个数。你的表中只有1条包含这个数组的记录,所以返回1,这是DjangoCount聚合函数的正常行为,但不是你需要的统计逻辑。


解决方案

根据你使用的数据库不同,我们可以通过调用数据库原生的JSON数组长度函数来实现需求,效率比在Python层面处理更高。

1. 针对PostgreSQL(推荐,Django对PostgreSQL的JSONB支持更完善)

PostgreSQL提供了jsonb_array_length函数专门用于统计JSON数组的元素数量,我们可以通过自定义Func来调用它:

from django.db.models import Func, IntegerField

class JSONArrayLength(Func):
    function = 'jsonb_array_length'
    output_field = IntegerField()

# 统计单条记录的数组长度
result = TopCountries.objects.aggregate(count=JSONArrayLength('top_countries'))
# 输出结果: {'count': 3}

如果你的表中有多条记录,想要统计每条记录的数组长度,可以用annotate:

# 为每条记录添加数组长度字段
queryset = TopCountries.objects.annotate(country_count=JSONArrayLength('top_countries'))
# 查看结果
for obj in queryset:
    print(obj.country_count)  # 输出对应记录的top_countries数组长度

2. 针对MySQL或SQLite

MySQL和SQLite分别提供了JSON_LENGTH和json_array_length函数,同样可以用自定义Func实现:

MySQL版本:

from django.db.models import Func, IntegerField

class JSONLength(Func):
    function = 'JSON_LENGTH'
    output_field = IntegerField()

result = TopCountries.objects.aggregate(count=JSONLength('top_countries'))

SQLite版本:

from django.db.models import Func, IntegerField

class JSONArrayLength(Func):
    function = 'json_array_length'
    output_field = IntegerField()

result = TopCountries.objects.aggregate(count=JSONArrayLength('top_countries'))

3. 小数据量场景:Python层面处理

如果你的数据量很小,也可以先获取模型实例,再在Python中计算数组长度:

obj = TopCountries.objects.first()
# 处理字段为空的情况
country_count = len(obj.top_countries) if obj.top_countries else 0
print(country_count)  # 输出3

内容的提问来源于stack exchange,提问作者Process Exe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 21:27:39