Postgresql - json 更新数组中对象的键

Postgresql - json update key of object in array

我的数据库中有以下 json:

[
    {"schedule_id":1,"datetime":"2017-05-12 00:00:00","status":"available"},
    {"schedule_id":2,"datetime":"2017-05-12 02:00:00","status":"available"}
]

我想更新 schedule_id = 2.

对象的 status 属性

我找到了类似的东西,但这需要数组中对象的索引:

select 
jsonb_set('[
    {"schedule_id":1,"datetime":"2017-05-12 00:00:00","status":"available"},
    {"schedule_id":2,"datetime":"2017-05-12 02:00:00","status":"available"}
]', 
'{1, status}', 
'"booked"')

`

您可以使用 jsonb_array_elements() 取消嵌套数组,修改过滤后的元素,最后使用 jsonb_agg(). 将结果聚合到 json 数组中 使用简单的连接运算符替换内部 json 对象。

示例(jsonb_pretty() 不需要,用于良好的输出):

with my_table(data) as (
values(
    '[
        {"schedule_id":1,"datetime":"2017-05-12 00:00:00","status":"available"},
        {"schedule_id":2,"datetime":"2017-05-12 02:00:00","status":"available"}
    ]'::jsonb)
)

select
    jsonb_pretty(jsonb_agg(
        case value->>'schedule_id'
        when '2' then value || '{"status":"booked"}'
        else value
        end
    ))
from my_table,
jsonb_array_elements(data);

                jsonb_pretty                
--------------------------------------------
 [                                         +
     {                                     +
         "status": "available",            +
         "datetime": "2017-05-12 00:00:00",+
         "schedule_id": 1                  +
     },                                    +
     {                                     +
         "status": "booked",               +
         "datetime": "2017-05-12 02:00:00",+
         "schedule_id": 2                  +
     }                                     +
 ]
(1 row)

使用此更新 table 的最简单方法是将查询包含在自定义函数中,例如:

create or replace function change_schedule_status(schedule jsonb, id int, status text)
returns jsonb language sql as $$
    select
        jsonb_agg(
            case value->>'schedule_id'
            when id::text then value || jsonb_build_object('status', status)
            else value
            end
        )
    from jsonb_array_elements(schedule);
$$;

update search
set schedule = change_schedule_status(schedule, 2, 'booked')
where id = 1  -- probably the table has a primary key?
returning *;