使用 postgres 从 jsonb 数组中删除元素

Remove element from jsonb array with postgres

我在 postgres 中有一个 table 包含类型为 jsonb 的列,我曾经以这种格式保存在这个字段数组中。

post_id                             |questions                                                                                                                                                                                      |
------------------------------------|---------------------------------------
70071d97-06a8-401f-abfc-20ddada4f402|[{"question": "TEST QUESTION", "transaction_id": "ac547b52-72f3-444e-800c-46aaa48855a5"}, {"question":   "TEST QUESTION", "transaction_id": "ac547b52-72f3-444e-800c-46aaa48855ab"}]|

我想删除该列表中基于 transaction_id 的项目。

post_id                             |questions                                                                                                                                                                                 |
------------------------------------|---------------------------------------
70071d97-06a8-401f-abfc-20ddada4f402|[{"question": "TEST QUESTION", "transaction_id": "ac547b52-72f3-444e-800c-46aaa48855a5"}]|

我尝试了几种方法,但 None 有效,我尝试了

select questions - '{"question": "TEST QUESTION", "transaction_id": "ac547b52-72f3-444e-800c-46aaa48855a5"}' from posts where post_id = '70071d97-06a8-401f-abfc-20ddada4f402';

step-by-step demo:db<>fiddle

UPDATE posts p
SET questions = data
FROM (
    SELECT
        questions,
        jsonb_agg(elems.value) AS data                       -- 3
    FROM
        posts,
        jsonb_array_elements(questions) elems                -- 1
    WHERE                                                    -- 2
        not (elems.value ->> 'transaction_id' = 'ac547b52-72f3-444e-800c-46aaa48855a5')
    GROUP BY questions
) s
WHERE s.questions = p.questions;
  1. 将数组扩展为每个数组元素一行
  2. 过滤掉要删除的元素
  3. 将所有剩余元素分组到一个新数组中

感谢 S-Man 回复。我能够实现我想要的。

update edz_posts set questions =     
(SELECT
    '[]'::jsonb || jsonb_agg(elems.value)
FROM
    edz_posts,
    jsonb_array_elements(questions) elems 
where post_id = :post_id and universe_id=:universe_id
and not (elems.value ->> 'transaction_id' = :transaction_id)
group by questions)
where post_id = :post_id and universe_id=:universe_id
;
update edz_posts set questions = '[]'::jsonb where questions is null ;