Jsonb_set: как обновить ВСЕ элементы массива ключом - PullRequest
0 голосов
/ 11 июня 2019

У меня есть таблица 'вещей' с набором столбцов

id | name | data
1  | 'hi' | [{name: 'what', amount: 10}, {name:'koo', amount: 15}, {name: 'boo', amount: 13}] 

Я хочу изменить значение на 0 во всех элементах массива.Т.е. я хочу, чтобы результат был

[{name: 'what', amount: 0}, {name:'koo', amount:0}, {name: 'boo', amount: 0}]

Когда я это сделаю

UPDATE      things
SET         data = jsonb_set(data, '{0,amount}', '0', false)
WHERE       id=1

Это работает, но только устанавливает значение первого элемента массива равным 0. Т.е. результат равен

[{name: 'what', amount: 0}, {name:'koo', amount: 15}, {name: 'boo', amount: 13}] 

Я хочу, чтобы все они были равны 0.

Как мне это сделать?

1 Ответ

0 голосов
/ 11 июня 2019

Вы можете разделить его на части, обновить и снова соединить:

select id, 
       name, 
       jsonb_agg(jsonb_set(array_elems, '{amount}', '0')) -- update each element of the array and aggregate them back together
FROM things
JOIN LATERAL (
    select jsonb_array_elements(data) -- split the array into each element
) sub(array_elems) ON TRUE
GROUP BY id, name;
 id | name |                                          jsonb_agg
----+------+---------------------------------------------------------------------------------------------
  1 | hi   | [{"name": "what", "amount": 0}, {"name": "koo", "amount": 0}, {"name": "boo", "amount": 0}]

Вот шаг обновления таблицы.

WITH updated_data AS (
  select id, 
       jsonb_agg(jsonb_set(array_elems, '{amount}', '0')) as updated
  FROM things
  JOIN LATERAL (
    select jsonb_array_elements(data) -- split the array into each element
  ) sub(array_elems) ON TRUE
  GROUP BY id
)
UPDATE things set data = updated
FROM updated_data 
WHERE things.id = updated_data.id;
...