2016-11-15 31 views
0

如何根据对象的某个键的值从数组中删除对象?如何删除基于嵌套键值的JSONB列中的数组元素?

该数组嵌套在父对象中。

下面是一个示例结构:

{ 
    "foo1": [ { "bar1": 123, "bar2": 456 }, { "bar1": 789, "bar2": 42 } ], 
    "foo2": [ "some other stuff" ] 
} 

我可以删除基于的bar1的值的数组元素?

我可以查询基于使用bar1值:columnname @> '{ "foo1": [ { "bar1": 123 } ]}',但我没有运气找到一种方法,同时保持一切完好无损从foo1删除{ "bar1": 123, "bar2": 456 }

感谢


运行的PostgreSQL 9.6

回答

2

假设你要搜索特定的对象具有一定价值的内部对象,此特定对象可以在阵列中的任何地方出现,您需要解压缩文档和每个阵列,测试内部子文档以进行控制并删除,然后重新组装阵列和JSON文档(未经测试):

SELECT id, jsonb_build_object(key, jarray) 
FROM (
    SELECT foo.id, foo.key, jsonb_build_array(bar.value) AS jarray 
    FROM ( SELECT id, key, value 
      FROM my_table, jsonb_each(jdoc)) foo, 
     jsonb_array_elements(foo.value) AS bar (value) 
    WHERE NOT bar.value @> '{"bar1": 123}'::jsonb 
    GROUP BY 1, 2) x 
GROUP BY 1; 
现在

,这看起来可能有点晦涩难懂,所以百般挑剔你:

SELECT id, key, value 
FROM my_table, jsonb_each(jdoc) 

这将使用你的桌子上的横向联接采取JSON文件jdoc并把它变成一组行foo(id, key, value)其中value包含数组。 id是您的表的主键。

然后我们得到:

SELECT foo.id, foo.key, jsonb_build_array(bar.value) AS jarray 
FROM foo, -- abbreviated from above 
    jsonb_array_elements(foo.value) AS bar (value) 
WHERE NOT bar.value @> '{"bar1": 123}'::jsonb 
GROUP BY 1, 2 

这将使用另一种横向连接到阵列解压到bar(value)行。现在可以使用包含运算符搜索这些对象以从结果集中删除对象:WHERE NOT bar.value @> '{"bar1": 123}'::jsonb。在选择列表中,阵列由idkey重新组装,但现在没有违规的子文档。

最后,在主查询的JSON文件重新组装:

SELECT id, jsonb_build_object(key, jarray) 
FROM x -- from above 
GROUP BY 1; 

了解的重要一点是,PostgreSQL的JSON功能只在JSON文件,你可以明确地指示的水平运行。通常,这是文档的顶层,除非您在文档中具有某个级别的明确路径(如{foo1, 0, bar1},但您没有)。在这个级别的操作中,您可以解压缩以执行处理,例如移除对象。