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.
来做我的测试用例
我有一个 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.