【问题标题】:How to delete array element in JSONB column based on nested key value?如何根据嵌套键值删除 JSONB 列中的数组元素?
【发布时间】:2017-03-28 20:24:09
【问题描述】:

如何根据对象键之一的值从数组中删除对象?

数组嵌套在父对象中。

这是一个示例结构:

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

我可以根据bar1的值删除一个数组元素吗?

我可以使用 columnname @> '{ "foo1": [ { "bar1": 123 } ]}' 基于 bar1 值进行查询,但我没有找到一种方法来从 foo1 中删除 { "bar1": 123, "bar2": 456 },同时保持其他所有内容不变。

谢谢


运行 PostgreSQL 9.6

【问题讨论】:

    标签: arrays postgresql jsonb


    【解决方案1】:

    假设您要搜索具有某个值的内部对象的特定对象,并且该特定对象可以出现在数组中的任何位置,您需要将文档和每个数组解包,测试内部子- 用于包含和删除的文档,然后重新组合数组和 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},但您没有该路径)。在该级别的操作中,您可以解包以进行处理,例如移除对象。

    【讨论】:

    • 我必须使用jsonb_agg 而不是jsonb_build_array 否则我会得到ERROR: column "bar.value" must appear in the GROUP BY clause or used in aggregate function
    猜你喜欢
    • 2016-04-28
    • 2019-09-12
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    • 2019-06-04
    • 2010-12-12
    相关资源
    最近更新 更多