Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PostgreSQL中使用非结构化数据在JSONB列中搜索_Postgresql_Jsonb - Fatal编程技术网

在PostgreSQL中使用非结构化数据在JSONB列中搜索

在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

我的表中有一个JSONB列,它在PostgreSQL数据库中存储非结构化数据。我需要搜索一个特定的键值对,但我不知道该键值的确切位置。 例如,如果我正在搜索

“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版中有什么方法可以做到这一点吗?