Select PostgreSQL JSONB 列的给定键内的条目数

Select number of entries inside a given key for a PostgreSQL JSONB column

我有一个 jsonb 列,示例内容如下:

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

我想找到 'myMap' 中的条目数大于/等于/小于某个整数的所有行——我有几百万这样的行,所以如果索引可以也可以用!

在上面的示例中,'myMap' 中有 4 个条目。所以对于类似 "select * from myTable where jsonb_key_length(myJsonbColumn -> 'myMap') = 4" 的查询,应该返回上面的行。 [假设有一个函数 jsonb_key_length() returns 给定 json 对象的长度]

我在这里发现了类似的问题:Postgres json key count

但是,它需要键的名称,这可以不使用键名来完成吗?

解决方案

Thanks @jmelesky for his suggestion.

以下查询对我有用:

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

Including @jmelesky's suggestion

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;

Found another, even faster solution

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

如果有更好的方法对此查询建模,请提出建议。谢谢!

有一个function叫做json_object_keys,这可能是这个问题的关键部分。它需要一个 json 对象和 returns 键作为关系的行。

=# 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.

来做我的测试用例