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

Django PostgreSQL中JSONField顶层键值的聚合求和最优方案

问题解决:Django JSONField顶层键值的总和计算

模型定义

我定义了如下简单模型:

import random
import string
from django.db import models


def random_default():
    random_str = "".join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))
    return {"random": random_str, "total_price": random.randint(1, 100)}


class Foo(models.Model):
    cart = models.JSONField(default=random_default)

需求与低效实现

我想获取所有Foo实例中total_price的总和。用原生Python可以实现,但效率很低:

sum(foo.cart["total_price"] for foo in Foo.objects.all())

失败的聚合尝试

我试了两种Django聚合查询,都没能正常运行:

1. 尝试1

Foo.objects.aggregate(total=models.Sum(Cast('cart__total_price', output_field=models.IntegerField())))

错误信息:

django.db.utils.DataError: cannot cast jsonb object to type integer

2. 尝试2

Foo.objects.aggregate(total=models.Sum('cart__total_price', output_field=models.IntegerField()))

错误信息:

django.db.utils.ProgrammingError: function sum(jsonb) does not exist
LINE 1: SELECT SUM("core_foo"."cart") AS "total" FROM "core_foo"
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

核心问题

获取JSONField顶层键值总和的正确/最优方法是什么?


版本信息

  • Python 3.8
  • Django 3.1.X

解决方案

针对Django 3.1+和PostgreSQL(JSONField默认使用jsonb存储),需要先正确提取JSON字段中的total_price值,再完成类型转换与聚合:

方法1:使用KeyTextTransform + Cast

from django.db.models import IntegerField, Sum, Cast
from django.db.models.fields.json import KeyTextTransform

total = Foo.objects.aggregate(
    total=Sum(
        Cast(
            KeyTextTransform('total_price', 'cart'),
            output_field=IntegerField()
        )
    )
)['total']

KeyTextTransform负责从JSON字段中提取指定键的字符串值,再通过Cast转换为整数类型,最后用Sum完成聚合计算。

方法2:使用原生JSON操作符

直接借助PostgreSQL的JSON操作符简化逻辑:

from django.db.models import Sum, IntegerField
from django.db.models.functions import Cast

total = Foo.objects.aggregate(
    total=Sum(
        Cast('cart->>\'total_price\'', output_field=IntegerField())
    )
)['total']

cart->>'total_price'是PostgreSQL的原生语法,直接提取JSON字段中total_price对应的文本值,转换为整数后求和。

两种方法都在数据库层面完成计算,无需将所有实例加载到内存,效率远高于原生Python遍历求和。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 08:47:08