2016-05-13 68 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