我有一个模型,它的字段 data
类型为 JSONField
,来自 django.contrib.postgres.fields
。 json结构是这样的:
{'aa': 1, 'bb': 2, 'cc': 4}
我想聚合 aa
和 cc
键的总和 - 所以在这种情况下,它将是 5。另外 - 我不能保证 aa
或 cc
将在 json 中。
这可能吗?如果是这样 - 我想按聚合数据排序。
示例:
- id: 1, data = {'aa': 1, 'bb': 2, 'cc':4}
- id: 2, data = {'aa': 3, 'bb': 2}
- id: 3, data = {'cc': 7}
- id: 4, data = {'bb': 7}
我想做一个查询,比如:
MyModel.objects.aggregate(my_sum).order_by(my_sum)
聚合后查询集中的有序行将是:
- 编号:3
- 编号:1
- 编号:2
- 编号:4
谢谢!
最佳答案
我了解到您想对每一行的 a 值和 b 值求和,然后按总和值对每一行进行排序。对吧?
-> ->>
这是如何在 PostgreSQL 中选择 JSON 格式的键或值(我不知道它是否也适用于 MySQL 或其他,我通常使用 PostgreSQL)。
here里面有很好的资源.您在名为“data
”的列中的数据是 {"aa":3, "bb":2, "cc":5}
。所以你通过data->>'aa'
选择一个值。如果 {'classification':{'pc':5000}}
会怎样?您需要选择 pc 值。然后是data->'classification'->>'pc'
::表示法是强制转换操作。
CAST(data->'aa' AS INTEGER)
data->'aa'::int
类 RawSQL(sql, params, output_field=None)
RawSQL("((data->>'aa'::int), (0,)") 并不意味着如果 aa 不存在,它的值为 0。0 是参数。
queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))
好吧,如果你能像这样修改你的数据
- id: 1, data = {'aa': 1, 'bb': 2, 'cc':4}
- id: 2, data = {'aa': 3, 'bb': 2, 'cc':0}
- id: 3, data = {'cc': 7, 'bb': 0, 'cc':0}
- id: 4, data = {'bb': 7, 'bb': 0, 'cc':0}
这可行。
Contract.objects.annotate(
sumVal=RawSQL("((data->>'aa')::int)", (0,))+RawSQL("((data->>'cc')::int)",(0,)))
.order_by('sumVal')
我建议使用 Coalesce。这个问题的作者想通了。下面有代码。
raw_sql = "+".join(["COALESCE((data->>%s)::int, 0)" for _ in ['aa', 'cc'])
MyMoodel.objects.all()
.annotate(my_sum=RawSQL(raw_sql, params=('aa', 'cc')))
.order_by('my_sum')
关于python - django - 聚合 json 字段特定键并按聚合排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45301976/