在PostgreSQL中使用非结构化数据在JSONB列中搜索
我的表中有一个JSONB列,它在PostgreSQL数据库中存储非结构化数据。我需要搜索一个特定的键值对,但我不知道该键值的确切位置。 例如,如果我正在搜索在PostgreSQL中使用非结构化数据在JSONB列中搜索,postgresql,jsonb,Postgresql,Jsonb,我的表中有一个JSONB列,它在PostgreSQL数据库中存储非结构化数据。我需要搜索一个特定的键值对,但我不知道该键值的确切位置。 例如,如果我正在搜索 “name”: “John” 数据可能如下所示: { “id”: 1, “name”: “John” “cars”: [] } select t.* from the_table where exists (select * from flatten(t.the
“name”: “John”
数据可能如下所示:
{
“id”: 1,
“name”: “John”
“cars”: []
}
select t.*
from the_table
where exists (select *
from flatten(t.the_column)
where t.key = 'name'
and t.value = 'John');
但是,在另一行中,该键值对可能出现在数组或另一个对象中(不在第一级)
在9.6中,我能想到的唯一方法就是创建一个递归遍历所有元素并返回JSON值“展平”视图的函数
create or replace function flatten(p_input jsonb)
returns table(key text, value text)
as
$$
begin
if jsonb_typeof(p_input) = 'array' then
return query
select f.*
from jsonb_array_elements(p_input) as a(element)
cross join flatten(a.element) f;
else
return query
select e.key, e.value #>> '{}'
from jsonb_each(p_input) as e(key, value)
where jsonb_typeof(e.value) not in ('object', 'array')
union all
select f.*
from jsonb_each(p_input) as t(key,value)
cross join flatten(t.value) as f
where jsonb_typeof(t.value) = 'object'
union all
select f.*
from jsonb_each(p_input) as t(key,value)
cross join jsonb_array_elements(t.value) as a(element)
cross join flatten(a.element) as f
where jsonb_typeof(t.value) = 'array';
end if;
end;
$$
language plpgsql;
然后你可以这样使用它:
{
“id”: 1,
“name”: “John”
“cars”: []
}
select t.*
from the_table
where exists (select *
from flatten(t.the_column)
where t.key = 'name'
and t.value = 'John');
您使用的是哪个Postgres版本?@a_horse_,没有名字版本9.6.14那么这将非常困难。在Postgres 12中,您可以执行
操作,其中_列@?'$.*?(@.name==“John”)
在9.6版中有什么方法可以做到这一点吗?