2017-07-25 166 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