从嵌套 json 中删除值 - postgres
Delete value from nested json - postgres
我有下面建模的 json 块。我想根据样本中的 AAA
和 BBB
id
从 my_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;
我有下面建模的 json 块。我想根据样本中的 AAA
和 BBB
id
从 my_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.
-- 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;