Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.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
Sql 关于嵌套/递归元素的Postgres JSONB查询_Sql_Json_Postgresql - Fatal编程技术网

Sql 关于嵌套/递归元素的Postgres JSONB查询

Sql 关于嵌套/递归元素的Postgres JSONB查询,sql,json,postgresql,Sql,Json,Postgresql,我有一个嵌套的层次结构,用JSON表达,例如: { "id":1, "children": [ { "id":2 }, { "id": 3, "children": [ { "id": 4 } ] } ] } postgres能否回答一个查询:记录是否在文档的任何部分包含“id”:4 如果是,这些查询是否由9.4版中添加的JSONB索引支持?更新:感谢reddit上的Theralgaxbo,我们从我的原始

我有一个嵌套的层次结构,用JSON表达,例如:

{
   "id":1,
   "children": [
      { "id":2 },
      { "id": 3, "children": [
         { "id": 4 }
         ]
      }
   ]
}
postgres能否回答一个查询:记录是否在文档的任何部分包含
“id”:4


如果是,这些查询是否由9.4版中添加的JSONB索引支持?

更新:感谢reddit上的Theralgaxbo,我们从我的原始代码开始,开发了更简洁的代码:

with recursive deconstruct (jsonlevel) as(
    values ('{"id":1,"children":[{"id":2},{"id":3,"children":[{"id":4}]}]}'::json)

    union all

    select 
        case left(jsonlevel::text, 1)
            when '{' then (json_each(jsonlevel)).value
            when '[' then json_array_elements(jsonlevel)
        end as jsonlevel
    from
        deconstruct
    where
        left(jsonlevel::text, 1) in ('{', '[')
)
select * from deconstruct where case when left(jsonlevel::text, 1) = '{' then jsonlevel->>'id' = '4' else false end;
我的原始答复如下:

我疯狂地进行实验,最终得出了如下结论:

with recursive ret(jsondata) as
(select row_to_json(col)::text jsondata from 
json_each('{
   "id":1,
   "children": [
      { "id":2 },
      { "id": 3, "children": [
         { "id": 4 }
         ]
      }
   ]
}'::json) col
union 
select case when left(jsondata::text,1)='[' then row_to_json(json_each(json_array_elements(jsondata)))::text
when left((jsondata->>'value'),2)='{}' then null::text
when left((jsondata->>'value')::text,1)='[' then row_to_json(json_each(json_array_elements(jsondata->'value')))::text
else  ('{"key":'||(jsondata->'key')||', "value":'||(jsondata->'value')||'}')::json::text end jsondata 
from (
select row_to_json(json_each(ret.jsondata::json)) jsondata
from ret) xyz

)
select max(1) from ret
where jsondata::json->>'key'='id' 
and jsondata::json->>'value'='1'

遗憾的是,我尝试用9.3解决这个问题,但是在让相同的代码在对象和数组上运行时遇到了问题。事实上,我认为在9.4中这可能要容易得多。我开始编写一个递归查询来完成它,但唉,我失败了——反正今天就失败了。不管怎样,我想出了一个方法,根据json字段文本表示的第一个字符来检测它是数组还是对象。可能无法直接回答您的问题,但我使用JSONSelect和PLV8来处理更复杂的JSON遍历和查询任务。花了一些时间进行设置,但它对我们来说运行良好。请随意编辑此内容,我实际上希望看到改进完成,或者当您向它抛出大量不同的数据时,您至少可以指出任何错误。感谢Joe提供的代码。老实说,您的SQL刚刚证实了我的担忧——它太复杂了,我无法证明它的合理性——我不希望团队中的每个人都成为博士后大师,以便了解发生了什么。我想我有两个选择:将我的JSON层次结构扁平化为一个带有ParentID的简单列表,或者忘记在Postgres中执行此操作,并在应用程序级别进行查询。有了9.4和jsonb,这将更容易。。现在,如果需要的话,您可以很容易地编写一个函数来隐藏一些复杂性。此外,如果您愿意安装V8语言,它具有javascript的功能,javascript甚至更支持JSON。