追加到 jsonb 数组中并根据键更新现有记录

Append in jsonb array and update existing record based on a key

我有一个 table media 和一个包含空数组的 jsonb 数组字段 pictures .

我的想法是,每次我追加一个新的 json 对象时,我都想将任何先前对象的默认属性从 true 切换为 false。

示例对象:

{"file": "file.jpg", "default": true}

我用 2 个不同的查询完成了这个。

一个用于插入新记录:

update media
set pictures = jsonb_set(
    pictures,
    concat('{' , jsonb_array_length(pictures) , '}')::text[],
    jsonb_build_object('file', 'somepicture.jpg', 'default', true)
)
where user_id = 8

还有一个用于从 default: true 切换到 default:false

update media
set pictures =
(
    select
        jsonb_agg(
            case when value->>'default' = 'true' and value->>'file' != 'somepicture.jpg'
            then value || jsonb_build_object('default', false)
            else value
            end
        )
    from jsonb_array_elements(media.pictures)
)
where user_id = 8

我的最终图片数组:

[
 {
  "file": "previouspicture.jpg",
  "default": false
 },
 {
  "file": "somepicture.jpg",
  "default": true
 }
]

我怎样才能实现同样的事情,只有一个查询?

使用额外的 jsonb_set() 来更新之前的对象。您必须使用 coalesce() 才能从空数组开始:

update media
set pictures = jsonb_set(
    coalesce(
        jsonb_set(
            pictures,
            array[(jsonb_array_length(pictures)-1)::text],
            pictures->jsonb_array_length(pictures)-1 || '{"default": false}'
            ), 
        pictures
    ),
    array[(jsonb_array_length(pictures))::text],
    jsonb_build_object('file', 'filename.jpg', 'default', true)
)
where user_id = 8
returning *;

DbFiddle.