2016-05-13 69 views
1

我有一個jsonb柱與樣本內容給定鍵裏面的條目選擇號碼如下:爲一個PostgreSQL JSONB列

{"kay1": val1, "myMap": {"UniqueKey1": "UniqueValue1", "UniqueKey2": "UniqueValue2", "UniqueKey3": "UniqueValue3", "UniqueKey4": "UniqueValue4"}, "key2": {"key3": {"key4": "val4"}, "val3": {"key5": "val5"}} 

我想找到其中的「我的地圖」條目的數量更大的所有行比/等於/小於某個整數 - 我有幾百萬這樣的行,所以如果索引也可以使用,這將是有幫助的!

在上面的示例中,'myMap'中有4個條目。因此對於像「select * from myTable where jsonb_key_length(myJsonbColumn - >'myMap')= 4」的查詢,應該返回上面的行。 [假設有一個函數jsonb_key_length()返回給定的json對象的長度]

我在這裏找到類似的問題:Postgres json key count

但是,它需要密鑰的名稱,這可以不使用密鑰名稱來完成?

解決方案

感謝@jmelesky了他的建議。

下面的查詢工作對我來說:

SELECT id, count(elements) 
FROM (SELECT id, jsonb_object_keys(column -> 'myMap') AS elements 
     FROM myTable GROUP BY id 
    ) x 
GROUP BY id 

包括@ jmelesky的建議

SELECT id, (SELECT count(*) 
      FROM (SELECT jsonb_object_keys(a->'myMap') 
        FROM test_json x where x.id = y.id 
       ) z 
      ) count 
FROM test_json y group by id; 

發現了另一個,甚至更快的解決方案

SELECT id, ARRAY_LENGTH(ARRAY(SELECT jsonb_object_keys(column -> 'myMap')), 1) AS count 
FROM myTable 

要使用索引:
創建一個函數:

CREATE OR REPLACE FUNCTION jsonb_object_keys_length(_j jsonb) 
RETURNS INT LANGUAGE SQL IMMUTABLE AS 
'SELECT ARRAY_LENGTH(ARRAY(SELECT jsonb_object_keys(column -> 'myMap')), 1)'; 

創建索引:在查詢

CREATE INDEX idx_myMapCount ON myTable (jsonb_object_keys_length(column -> 'myMap')); 

使用功能:

SELECT id, jsonb_object_keys_length(column -> 'myMap') AS count 
FROM myTable 

請不要暗示,如果有一個更好的方法建模此查詢。謝謝!

回答

4

有一個functionjson_object_keys,這可能是這個問題的關鍵部分。它需要一個json對象並將這些鍵作爲關係的行返回。

=# create table test_json (a json); 
CREATE TABLE 
=# insert into test_json values ('{"kay1": 1, "myMap": {"UniqueKey1": "UniqueValue1", "UniqueKey2": "UniqueValue2", "UniqueKey3": "UniqueValue3", "UniqueKey4": "UniqueValue4"}, "key2": {"key3": {"key4": "val4"}, "val3": {"key5": "val5"}}}'); 
INSERT 0 1 
=# select json_object_keys(a) from test_json; 
json_object_keys 
------------------ 
kay1 
myMap 
key2 
(3 rows) 
=# select json_object_keys(a->'myMap') from test_json; 
json_object_keys 
------------------ 
UniqueKey1 
UniqueKey2 
UniqueKey3 
UniqueKey4 
(4 rows) 

從那裏,你可以包裝在一個子查詢,像這樣:

=# select count(*) from (select json_object_keys(a->'myMap') from test_json) x; 
count 
------- 
    4 
(1 row) 

編輯補充:有一個jsonb當量(jsonb_object_keys),這與jsonb值相同的工作原理。對不起,我傾向於在香草json中做我的測試用例。

+1

感謝您的回覆。但是,這個查詢不能按預期工作,因爲我有多行,我想爲每行查找此計數。 例如: ID |列 1 | {「kay1」:val1,「myMap」:{「UniqueKey1」:「UniqueValue1」,「UniqueKey2」:「UniqueValue2」,「UniqueKey3」:「UniqueValue3」,「UniqueKey4」:「UniqueValue4」},「key2」 「key3」:{「key4」:「val4」},「val3」:{「key5」:「val5」}} 2 | {「kay1」:val1,「myMap」:{「UniqueKey21」:「UniqueValue21」,「UniqueKey22」:「UniqueValue22」},「key2」:{「key3」:{「key4」:「val4」},「val3 「:{」key5「:」val5「}} 我想要類似: id | myMap_count 1 | 4 2 | 2 –

+1

事情是這樣的: SELECT ID,計數(元素)FROM test_json TJ,jsonb_each_text(tj.a - > MYMAP')AS GROUP BY ID 元素但使用子查詢,而不是 '從' –

+0

這是比較直截了當。類似於'select id,(select test(*)from(從test_json x選擇jsonb_object_keys(a - >'myMap'),其中x.id = y.id)z)從test_json計數y group by id;'should do。 – jmelesky