从嵌套 json 中删除值 - postgres

Delete value from nested json - postgres

我有下面建模的 json 块。我想根据样本中的 AAABBB idmy_items 中选择性地删除单个块。即,如果我尝试删除 my_items 下的 AAA 块,我只想删除 {"id" : "AAA"},但如果想删除 BBB 块,它将删除较大的 [=21] =]块。

我知道我可以使用 #- 删除整个块,例如 SELECT '{sample_json}'::jsonb #- '{my_items}' 会清除整个 my_items 块。但我不知道如何使用它有条件地删除 json 父块下的子项。我还使用了类似于此示例的代码,通过读入嵌套结构的节点并将新数据写入并重写,将数据附加到嵌套结构中。 UPDATE data SET value= jsonb_set(value, '{my_items}', value->'items' || (:'json_to_adds'), true) where id='testnofeed'.

但我不知道如何将这些方法应用到:1) 使用 #- 删除嵌套结构中的数据或 2) 使用 `jsonb_set[ 执行相同操作=38=]。任何人都对如何使用其中任何一种(或其他方法)执行此操作有任何指导。

{
  "urlName" : "testurl",
  "countryside" : "",
  "description" : "",
  "my_items" : [
     {
       "id" : "AAA"
     },
    {
      "name" : "TestRZ",
      "id" : "BBB",
      "description" : ""
    },
 ],
   "name" : "TheName"
 }

数据存储在value jsonb。当我更新时,我将能够传入一个唯一的 kind,这样它只会在 db.

的一行中更新这个 json
  -- Table Definition
  CREATE TABLE "public"."data" (
 "id" varchar(100) NOT NULL,
 "kind" varchar(100) NOT NULL,
 "revision" int4 NOT NULL,
 "value" jsonb
  );

这适用于 PostgreSQL 12 及更高版本,支持 jsonpath。如果没有jsonpath,请留言。

with data as (
  select '{
  "urlName" : "testurl",
  "countryside" : "",
  "description" : "",
  "my_items" : [
     {
       "id" : "AAA"
     },
    {
      "name" : "TestRZ",
      "id" : "BBB",
      "description" : ""
    }
 ],
   "name" : "TheName"
 }'::jsonb as stuff
)
select jsonb_set(stuff, '{my_items}',
                   jsonb_path_query_array(stuff->'my_items', '$ ? (@."id" <> "AAA")'))
  from data;

                                                                     jsonb_set                                                                     
---------------------------------------------------------------------------------------------------------------------------------------------------
 {"name": "TheName", "urlName": "testurl", "my_items": [{"id": "BBB", "name": "TestRZ", "description": ""}], "countryside": "", "description": ""}
(1 row)

要直接更新 table,语句为:

update data
   set value = jsonb_set(value, '{my_items}',
                   jsonb_path_query_array(value->'my_items', 
                                          '$ ? (@."id" <> "AAA")'));

这适用于 PostgreSQL 12 之前的版本:

with data as (
  select 1 as id, '{
  "urlName" : "testurl",
  "countryside" : "",
  "description" : "",
  "my_items" : [
     {
       "id" : "AAA"
     },
    {
      "name" : "TestRZ",
      "id" : "BBB",
      "description" : ""
    }
 ],
   "name" : "TheName"
 }'::jsonb as stuff
), expand as (
  select d.id, d.stuff, e.item, e.rn
    from data d
   cross join lateral jsonb_array_elements(stuff->'my_items') with ordinality as e(item, rn)
)
select id, jsonb_set(stuff, '{my_items}', jsonb_agg(item order by rn)) as new_stuff
  from expand
 where item->>'id' != 'AAA'
 group by id, stuff;

 id |                                                                     new_stuff                                                                     
----+---------------------------------------------------------------------------------------------------------------------------------------------------
  1 | {"name": "TheName", "urlName": "testurl", "my_items": [{"id": "BBB", "name": "TestRZ", "description": ""}], "countryside": "", "description": ""}
(1 row)

直接更新这个有点复杂:

with expand as (
  select d.id, d.value, e.item, e.rn
    from data d
   cross join lateral jsonb_array_elements(value->'my_items')
         with ordinality as e(item, rn)
), agg as (
  select id, jsonb_set(value, '{my_items}', jsonb_agg(item order by rn)) as new_value
    from expand
   where item->>'id' != 'AAA'
   group by id, value
)
update data
   set value = agg.new_value
  from agg
 where agg.id = data.id;