Обновить значение атрибута в массиве объектов postgresql jsonb в нескольких записях - PullRequest
0 голосов
/ 11 июля 2020

Я пытаюсь обновить значение tit в трех записях базы данных, которые являются частью объекта массива jsonb, чтобы изменить заголовок gid 1 на 'newTitle Group 1' вместо просто 'group 1', используя postgresql и python .

create table groups (name varchar, grp jsonb)
 insert into groups (name, grp) values 
  ('joe', [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}]),
  ('harry', [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
  ('moe' , [{"gid": "1", "ona": "joe", "tit": "group 1 "}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])

Я хочу получить результат:

  ('joe', [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}]),
  ('harry', [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])
  ('moe' , [{"gid": "1", "ona": "joe", "tit": "newTitle Group 1'"}, {"gid": "2", "ona": "harry", "tit": "tester1 group 2"}, {"gid": "3", "ona": "moe", "tit": "group 3"}])

Я не нашел способа сделать это, помогите пожалуйста. Похоже, что большинство возможностей postgresql 9.5 предназначены для объектов jsonb, но не для массивов объектов.

Я пытался использовать множество примеров в Интернете, но все, похоже, не помогли. Я бы также подумал об использовании оператора where в фактическом запросе, чтобы ограничить поиск записей jsonb, например, включая WHERE name IN ('harry', 'moe'), но пока просто нужно посмотреть, как решается эта проблема обновления basi c.

1 Ответ

0 голосов
/ 11 июля 2020

Просто нужно использовать функцию REPLACE(), включая преобразования :: text и :: jsonb в БД, без необходимости каких-либо дополнительных операций в коде python:

UPDATE groups
   SET grp = REPLACE(grp::text, '"tit": "group 1 "','"tit": "newTitle Group 1 "')::jsonb

Демо

Конечно, можно добавить условие where, например WHERE name IN ('harry', 'moe'), чтобы ограничить обновление.

ОБНОВЛЕНИЕ 1:

Если вам нужно выполнить обновление для записи spesifi c в объекте jsonb, например

WHERE j->>'ona' = 'joe', используйте jsonb_array_elements() функционирует в вашем операторе как:

UPDATE groups AS g
   SET grp = REPLACE(grp::text, '"tit": "group 1 "','"tit": "newTitle Group 1 "')::json
 WHERE g.name IN ( SELECT g.name 
                     FROM groups AS g 
                    CROSS JOIN jsonb_array_elements(grp) AS j 
                    WHERE j.value->>'ona' = 'joe' ) 

Демо

ОБНОВЛЕНИЕ 2:

Если вы хотите найти желаемое значение (gid=1 в данном случае ) в столбце jsonb динамически, чтобы получить путь, тогда можно использовать функцию jsonb_set() как:

WITH T AS
(
 SELECT ('{'||index-1||',tit}')::text[] AS path
   FROM groups AS g2 
  CROSS JOIN jsonb_array_elements(grp) 
   WITH ORDINALITY arr(j,index)
  WHERE j->>'gid'='1' 
)
UPDATE groups AS g
   SET grp = jsonb_set(grp,t.path,'"newTitle Group 1 "',false)
  FROM t

Демо

...