从 jsonb 数组中删除元素
Posted
技术标签:
【中文标题】从 jsonb 数组中删除元素【英文标题】:Remove element from jsonb array 【发布时间】:2019-03-05 10:02:57 【问题描述】:我有以下 jsonb。从数组页面中,我想删除名为“pageb”的元素。类似问题中提供的解决方案对我不起作用。
'
"data":
"id": "a1aldjfg3f",
"pages": [
"type": "pagea"
,
"type": "pageb"
],
"activity": "test"
'
我的脚本现在看起来像这样。它不会返回任何错误,但不会删除元素。
UPDATE database
SET reports = jsonb_set(reports, 'data,pages', (reports->'data'->'pages') - ('"type":"pageb"'), true)
WHERE reports->'data'->'pages' @> '["type":"pageb"]';
【问题讨论】:
Remove jsonb array element by value的可能重复 那个问题的解决方案对我不起作用。 【参考方案1】:-
运算符不能在这里应用,因为右边的操作数是一个定义键的字符串,per the documentation:
从左操作数中删除键/值对或字符串元素。键/值对根据其键值进行匹配。
从 json 数组中删除 json 对象可以通过解包数组并找到对象的索引来完成。使用这种方法的查询可能过于复杂,因此在这种情况下定义自定义函数非常方便。
create or replace function jsonb_remove_array_element(arr jsonb, element jsonb)
returns jsonb language sql immutable as $$
select arr- (
select ordinality- 1
from jsonb_array_elements(arr) with ordinality
where value = element)::int
$$;
还有更新:
update my_table
set reports =
jsonb_set(
reports,
'data,pages',
jsonb_remove_array_element(reports->'data'->'pages', '"type":"pageb"')
)
where reports->'data'->'pages' @> '["type":"pageb"]';
Working example in rextester.
【讨论】:
【参考方案2】:以下是 answer provided 的组合,用于可靠地删除数组内的元素和 PostgreSQL 使用 data-modifying WITH
statements 的能力,但它需要一个标识列(id
在我的test
表中)才能工作因为必要的相关性:
WITH new_reports AS (
SELECT
id,
reports #- array['data','pages',(position - 1)::text] AS new_value
FROM
test,
jsonb_array_elements(reports->'data'->'pages') WITH ORDINALITY arr(item, position)
WHERE
test.reports->'data'->'pages' @> '["type":"pageb"]'
AND
item->>'type' = 'pageb'
)
UPDATE test SET reports = new_reports.new_value FROM new_reports WHERE test.id = new_reports.id;
我使用的测试数据:
SELECT reports FROM test;
reports
-----------------------------------------------------------------------------------------------------
"data": "id": "a1aldjfg3f", "pages": ["type": "pagea", "type": "pagec"], "activity": "test"
"data": "id": "a1aldjfg3f", "pages": ["type": "pagea", "type": "pageb"], "activity": "test"
"data": "id": "a1aldjfg3f", "pages": ["type": "pageb", "type": "pagec"], "activity": "test"
(3 rows)
...执行查询后:
SELECT reports FROM test;
reports
-----------------------------------------------------------------------------------------------------
"data": "id": "a1aldjfg3f", "pages": ["type": "pagea", "type": "pagec"], "activity": "test"
"data": "id": "a1aldjfg3f", "pages": ["type": "pagea"], "activity": "test"
"data": "id": "a1aldjfg3f", "pages": ["type": "pagec"], "activity": "test"
(3 rows)
我希望这对你有用。
【讨论】:
【参考方案3】:你来了
do $$
declare newvar jsonb;
begin
newvar := jsonb ' "customer": "John Doe", "buy": ["product": "Beer","qty": 6,"product": "coca","qty": 5]';
newvar := jsonb_set(newvar,'buy', jsonb_remove((newvar->>'buy')::jsonb,'"product": "Beer"'));
newvar := jsonb_set(newvar,'buy', jsonb_add((newvar->>'buy')::jsonb,'"product": "cofe","qty": 6'));
RAISE NOTICE '%', newvar;
end $$
create or replace function jsonb_remove(arr jsonb, element jsonb)
returns jsonb language sql immutable as $$
select ('['||coalesce(string_agg(r::text,','),'')||']')::jsonb from jsonb_array_elements(arr) r where r @> element=false
$$;
create or replace function jsonb_add(arr jsonb, element jsonb)
returns jsonb language sql immutable as $$
select arr||element
$$;
【讨论】:
以上是关于从 jsonb 数组中删除元素的主要内容,如果未能解决你的问题,请参考以下文章