【发布时间】:2019-06-11 13:08:42
【问题描述】:
我想使用 SQL 检查 JSONB 列中是否存在属性。
使用这个我可以检查属性是否等于值:
SELECT count(*) AS "count" FROM "table" WHERE column->'node' @> '[{"Attribute":"value"}]'
我用什么语法来检查属性的存在?
【问题讨论】:
标签: sql json postgresql jsonb
我想使用 SQL 检查 JSONB 列中是否存在属性。
使用这个我可以检查属性是否等于值:
SELECT count(*) AS "count" FROM "table" WHERE column->'node' @> '[{"Attribute":"value"}]'
我用什么语法来检查属性的存在?
【问题讨论】:
标签: sql json postgresql jsonb
通常你会检查 null:
SELECT count(*) AS "count" FROM "table"
WHERE column->'node'->'Attribute' is not null
【讨论】:
? 操作符的意思是Does the string exist as a top-level key within the JSON value? 但是,你想检查一个key是否存在于嵌套的json对象数组中,所以不能直接使用操作符。您必须取消嵌套数组。
样本数据:
create table my_table(id serial primary key, json_column jsonb);
insert into my_table (json_column) values
('{"node": [{"Attribute":"value"}, {"other key": 0}]}'),
('{"node": [{"Attribute":"value", "other key": 0}]}'),
('{"node": [{"Not Attribute":"value"}]}');
在横向连接中使用jsonb_array_elements() 来找出键是否存在于数组的任何元素中:
select
id,
value,
value ? 'Attribute' as key_exists_in_object
from my_table
cross join jsonb_array_elements(json_column->'node')
id | value | key_exists_in_object
----+----------------------------------------+----------------------
1 | {"Attribute": "value"} | t
1 | {"other key": 0} | f
2 | {"Attribute": "value", "other key": 0} | t
3 | {"Not Attribute": "value"} | f
(4 rows)
但这并不是您所期望的。您需要汇总数组的结果:
select
id,
json_column->'node' as array,
bool_or(value ? 'Attribute') as key_exists_in_array
from my_table
cross join jsonb_array_elements(json_column->'node')
group by id
order by id
id | array | key_exists_in_array
----+--------------------------------------------+---------------------
1 | [{"Attribute": "value"}, {"other key": 0}] | t
2 | [{"Attribute": "value", "other key": 0}] | t
3 | [{"Not Attribute": "value"}] | f
(3 rows)
嗯,这看起来有点复杂。您可以更轻松地使用该功能:
create or replace function key_exists_in_array(key text, arr jsonb)
returns boolean language sql immutable as $$
select bool_or(value ? key)
from jsonb_array_elements(arr)
$$;
select
id,
json_column->'node' as array,
key_exists_in_array('Attribute', json_column->'node')
from my_table
id | array | key_exists_in_array
----+--------------------------------------------+---------------------
1 | [{"Attribute": "value"}, {"other key": 0}] | t
2 | [{"Attribute": "value", "other key": 0}] | t
3 | [{"Not Attribute": "value"}] | f
(3 rows)
【讨论】: