2017-07-25 171 views
0


我有一个dataJSONField类型的字段django.contrib.postgres.fields的模型。 JSON的结构是,像这样:django - 聚合JSON字段特定的键和聚合订单

{'aa': 1, 'bb': 2, 'cc': 4} 

我想聚集aacc键的总和 - 因此,在这种情况下,这将是5,而且 - 我不能答应,要么aacc将在json。
这可能吗?如果是这样 - 我想按汇总的数据进行排序。
实施例:

  1. ID:1,数据= { 'AA':1, 'BB':2, '抄送':4}
  2. ID:2,数据= { 'AA': 3, 'BB':2}
  3. ID:3,数据= { '抄送':7}
  4. ID:4,数据= { 'B-B':7}

我想要做一个查询,如:
MyModel.objects.aggregate(my_sum).order_by(my_sum)
聚集后的查询集有序行将是:

  1. ID:3
  2. ID:1
  3. ID:2
  4. ID:4

谢谢!

+0

您拥有模型的哪种类型的对象(实例或查询集)? –

+0

@NeErAjKuMaR - 我有一个查询集,我想根据模型字段进行聚合,并按汇总值 –

+0

进行排序,但是你说你需要json数据的键值总和 –

回答

1
YourModel.objects.annotate(aa=RawSQL("((data->>'aa')::int)", (0,)), 
          cc=RawSQL("((data->>'cc')::int)", (0,))) \ 
       .aggregate(total=Sum('aa')+Sum('cc')).order_by('total') 
+0

一些*解释*如何以及为什么这个作品会帮助海报... – joanolo

2

我知道你想为每一行总结一个值和b值,然后按总和值排序每一行。对?

-> ->>这是如何在PostgreSQL中选择JSON格式的键或值(我不知道它是否也适用于MySQL或其他,我通常使用PostgreSQL)。 here有很好的资源。您名为'data'的列中的数据为{"aa":3, "bb":2, "cc":5}。所以你选择一个值data->>'aa'。如果{'classification':{'pc':5000}}怎么办?你需要选择pc值。然后data->'classification'->>'pc'

::表示法是cast操作。

CAST(data->'aa' AS INTEGER) 

data->'aa'::int 

类RawSQL(SQL,则params,output_field =无)

RawSQL( “((数据 - >> 'AA' :: INT),(0,)”)并不意味着如果aa不存在,则它具有0值,0是params。

queryset.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,))) 

好吧,如果你可以修改你的数据是这样

  • ID:1,数据= { 'AA':1, 'BB':2, '抄送':4}
  • id:2 data = {'aa':3,'bb':2,'cc':0}
  • id:3,data = {'cc':7,'bb':0,'cc ':0}
  • ID:4,数据= {' B-B':7, 'BB':0, '抄送':0}

这可以工作。

Contract.objects.annotate(
sumVal=RawSQL("((data->>'aa')::int)", (0,))+RawSQL("((data->>'cc')::int)",(0,))) 
.order_by('sumVal') 

我建议使用合并。这个问题的作者想通了。下面有代码。

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') 
+0

我试图找出与Coalesce来覆盖的情况下,当'aa'或'cc'的关键不存在。这是一个有趣的问题,所以我花了相当长的时间弄清楚,但我不能。你可以查看[关于Coalesce的django手册](https://docs.djangoproject.com/en/dev/ref/models/database-functions/#coalesce)。我希望它给你任何想法来解决你的问题。 – Jayground

+0

所以我想出了如何使用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')' 请更新您的答案并我很乐意将其标记为答案 –

+0

哦,它工作?凉。我尝试将COALESCE放入注释中,但它不起作用。 – Jayground