Поиск и обновление элемента массива JSON в Postgres - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть столбец Jsonb, в котором хранится массив элементов, подобных следующему:

[ 
  {"id": "11", "name": "John", "age":"25", ..........}, 
  {"id": "22", "name": "Mike", "age":"35", ..........},
  {"id": "33", "name": "Tom",  "age":"45", ..........},
  .....
]

Я хочу заменить 2-й объект (id = 22) на совершенно новый объект. Я не хочу обновлять каждое свойство по одному, потому что есть много свойств, и все их значения могли бы измениться. Я хочу просто определить 2-й элемент и заменить весь объект.

Я знаю, что есть jsonb_set (). Однако для обновления 2-го элемента мне нужно знать его индекс массива = 1, чтобы я мог сделать следующее:

jsonb_set(data, '{1}', '{"id": "22", "name": "Don", "age":"55"}',true) 

Но я не мог найти способ найти и получить этот индекс. Кто-нибудь может мне помочь?

1 Ответ

0 голосов
/ 14 сентября 2018

Один из способов, который я могу придумать, - это объединить row_number и json_array_elements:

-- test data
create table test (id integer, data jsonb);
insert into test values (1, '[{"id": "22", "name": "Don", "age":"55"}, {"id": "23", "name": "Don2", "age":"55"},{"id": "24", "name": "Don3", "age":"55"}]');
insert into test values (2, '[{"id": "32", "name": "Don", "age":"55"}, {"id": "33", "name": "Don2", "age":"55"},{"id": "34", "name": "Don3", "age":"55"}]');

select subrow, id, row_number() over (partition by id) 
from (
    select json_array_elements(data) as subrow, id 
    from test
) as t;
                  subrow                  | id | row_number
------------------------------------------+----+------------
 {"id": "22", "name": "Don", "age":"55"}  |  1 |          1
 {"id": "23", "name": "Don2", "age":"55"} |  1 |          2
 {"id": "24", "name": "Don3", "age":"55"} |  1 |          3
 {"id": "32", "name": "Don", "age":"55"}  |  2 |          1
 {"id": "33", "name": "Don2", "age":"55"} |  2 |          2
 {"id": "34", "name": "Don3", "age":"55"} |  2 |          3

-- apparently you can filter what you want from here
select subrow, id, row_number() over (partition by id) 
from (
    select json_array_elements(data) as subrow, id 
    from test
) as t
where subrow->>'id' = '23';

Кроме того, подумайте о дизайне вашей схемы. Возможно, не самая лучшая идея хранить ваши данные таким образом.

...