Обновить вложенный ключ с полем postgres json в Rails

Я пытался обновить следующее:

{"boxes": {"book": 2, "moving": 2}, "goods": {}}

to :

{"boxes": {"book_new": 2, "moving": 2}, "goods": {}}

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

Мне удалось добавить новый элемент к данным, но не к вложенным полям!! как это:

Update moves SET data = data::jsonb || '{"bookasas": 2}'   WHERE data ->> 'boxes' LIKE '%book%';

Любая помощь приветствуется.


person user181452    schedule 29.08.2016    source источник
comment
Возможный дубликат Как изменить поля внутри новый тип данных PostgreSQL JSON?   -  person pozs    schedule 29.08.2016
comment
Вопрос касается, в частности, замены ключа json, поэтому это не дубликат.   -  person klin    schedule 29.08.2016
comment
@klin Единственная дополнительная информация над связанным вопросом заключается в том, что в PostgreSQL нет операции прямой замены: чтобы заменить пару ключ-значение, сначала необходимо удалить старый ключ и установить новый. Но поскольку ОП уже понял это (я хочу добавить новый ключ, а затем удалить старый), я думаю, что на него уже дан ответ. Но я согласен, этот вопрос находится в несколько серой зоне (насчет дублирования).   -  person pozs    schedule 29.08.2016


Ответы (1)


Нет функции замены ключа json, поэтому вам следует удалить старый объект и добавить новый:

update moves 
set data = jsonb_set(
    data::jsonb,
    array['boxes'],
    (data->'boxes')::jsonb - 'book' || jsonb_build_object('book_new', data->'boxes'->'book')
    )
where data ->> 'boxes' like '%book%'
returning *;

                         data                         
------------------------------------------------------
 {"boxes": {"moving": 2, "book_new": 2}, "goods": {}}
(1 row)
person klin    schedule 29.08.2016
comment
Я получаю HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. - person user181452; 29.08.2016
comment
Спасибо, это работает, но мне пришлось добавить ::text к «книге» и ::jsonb к (data->'boxes') - person user181452; 29.08.2016
comment
пожалуйста, обновите свой ответ, чтобы иметь эти два, и он будет идеальным, так что другие люди могут извлечь из этого пользу, еще раз большое спасибо! - person user181452; 29.08.2016
comment
Хорошо, я проверил это с data типа jsonb. - person klin; 29.08.2016
comment
о, я только что заметил, делая это, я теряю значение, потому что вы всегда присваиваете 2 новому значению! - person user181452; 29.08.2016
comment
Нет, нет, это решение объединяет данные в себя и работает случайным образом {"boxes": {"barry": 0, "boxes": {"picture": 0, "book_new": 2, "clothing": 0, "sdssdsdds": 2}, "goods": {}, "picture": 0, "book_new": 0, "bookasas": 2, "sdssdsdds": 2}, "goods": {}, "bookasas": 2} - person user181452; 29.08.2016
comment
Я попробовал старый, сначала добавил новый элемент, а затем удалил старый data::jsonb || '{"book_new": (data->'boxes')::jsonb->>'book'}' || (data->'boxes')::jsonb - 'book'::text , но получить значение из элемента неправильно. - person user181452; 29.08.2016
comment
Я немного запутался, решение хорошо работает с рассматриваемыми данными. - person klin; 29.08.2016
comment
Извините, моя ошибка, моя БД так запуталась с тестированием, последнее решение работает правильно (y) - person user181452; 29.08.2016