Postgres:更新 JSON 数组并删除与键匹配的元素

Postgres: Update JSON Array and remove element matched with key

鉴于下面的table

drop table if exists documents;
create table documents(docu_id text, attachments jsonb);
insert into documents values
('001', 
'[{"province":"test province","city":"test city","barangay":"test barangay,"street":"test ST"},
 {"province":"test province 2","city":"test city 2","barangay":"test barangay 2","street":"test street 2"}]'
),

('002', 
'[{"province":"test province 2 1":"VALENZUELA CITY","test barangay 2 1":"test barangay 2 1","street":"test street 2 1"},
 {"province":"test province 2 2","city":"test city 2 2","barangay":"test barangay 2 2","street":"test strett 2 2"}]'
);

如何更新 json 匹配街道关键词的数组:test ST

预期输出

[{"province":"test province 2","city":"test city 2","barangay":"test barangay 2","street":"test street 2"}]

[{"province":"test province 2 1":"VALENZUELA CITY","test barangay 2 1":"test barangay 2 1","street":"test street 2 1"},
     {"province":"test province 2 2","city":"test city 2 2","barangay":"test barangay 2 2","street":"test strett 2 2"}]

demo:db<>fiddle

SELECT
    docu_id,
    jsonb_agg(elements.value)                     -- 3
FROM
    documents,
    jsonb_array_elements(attachments) AS elements -- 1
WHERE elements ->> 'street' != 'test ST'          -- 2
GROUP BY docu_id                                  -- 3
  1. 将数组元素展开为一行,每行 jsonb_array_elements()
  2. 根据您的喜好过滤这些元素
  3. 使用聚合函数 jsonb_agg()
  4. 将剩余元素再次分组到 JSON 数组中

更新:

UPDATE documents d
SET attachments = s.new_attachments
FROM (
    SELECT
        docu_id,
        jsonb_agg(elements.value) AS new_attachments
    FROM
        documents,
        jsonb_array_elements(attachments) AS elements
    WHERE elements.value ->> 'street' != 'test ST'
    GROUP BY docu_id
) s
WHERE d.docu_id = s.docu_id

demo:db<>fiddle

正在更新 json 匹配数据的剩余值,而不是没有更新发生。它将更新为 null 或空 json.

UPDATE street_lov SET street = sub
FROM COALESCE((SELECT jsonb_agg(elements.value) as elements FROM street_lov,
jsonb_array_elements(street::jsonb) AS elements
WHERE elements.value ->> 'street' != 'test ST' 
AND id = (SELECT id FROM street_id)
GROUP BY id ), '[]') sub where street_lov.id = (select id from street_id)
RETURNING street_lov.id,street