Я пытаюсь добавить ключ к вложенному jsonb в postgres, но получаю ошибки. По сути, я начинаю с json как:
{"tel": "123", "name": "foo", "new_info": {"a": "bar"}}
и я хочу добавить {"b", "baz"}
в "new_info" так, чтобы результирующий jsonb был:
{"tel": "123", "name": "foo", "new_info": {"a": "bar", "b":"baz"}}
Я использую следующие команды для перехода к исходному jsonb:
CREATE TABLE mytable (
ID serial NOT NULL PRIMARY KEY,
data jsonb NOT NULL
);
INSERT INTO mytable (data)
VALUES
(
'{ "name": "foo", "tel": "123"}'
);
UPDATE mytable SET data = jsonb_set(data, '{new_info}', '{"a":"bar"}', TRUE) WHERE data @> '{"name": "foo"}' ;
и пытается использовать следующее для обновления «new_info», которая не работает:
WITH orig_new_info AS (SELECT data#>'{new_info}' FROM mytable WHERE data @> '{"name": "foo"}')
WITH updated_new_info AS (jsonb_set(orig_new_info, '{"b":"baz"}',TRUE ))
UPDATE mytable SET data = jsonb_set(data, '{new_info}', updated_new_info, TRUE) WHERE data @> '{"name": "foo"}';
Любые указатели очень ценятся!
ОБНОВЛЕНИЕ № 1:
За клинс отвечают следующие работы:
update mytable
set data = jsonb_insert(data, '{new_info}', data->'new_info' || '{"b":"baz"}', TRUE)
where data @> '{"name": "foo"}'
returning *;
Однако как можно избежать перезаписи существующих ключей, используя что-то вроде jsonb_insert. Другими словами, почему не работают следующие примеры?
#ex 1
update mytable
set data = jsonb_insert(data, '{new_info}', jsonb_insert(SELECT data->'new_info' FROM mytable WHERE data @> '{"name": "foo"}'), '{"b":"baz"}'),true)
where data @> '{"name": "foo"}'
returning *;
#ex2
WITH orig_new_info AS (SELECT data#>'{new_info}' FROM mytable WHERE data @> '{"name": "foo"}')
WITH updated_new_info AS(SELECT jsonb_insert(orig_new_info, orig_new_info ||'{"b":"bazer"}'))
update mytable
set data = jsonb_set(data, '{new_info}', updated_new_info, TRUE)
where data @> '{"name": "foo"}'
returning *;
Другими словами, в ответе клина рассматриваются только ключи верхнего уровня data
jsonb, а не ключи вложенного "new_info"
json, который находится внутри data
.
ОБНОВЛЕНИЕ № 2:
За клин обновлен ответ на следующие работы:
update mytable
set data = jsonb_insert(data, '{new_info, b}', '"baz"')
where data @> '{"name": "foo"}'
Однако, если "new_info"
не существует в data
, обновление успешно завершается без сохранения. Таким образом, следующие команды завершаются успешно, но данные не сохраняются:
DROP TABLE mytable;
CREATE TABLE mytable (
ID serial NOT NULL PRIMARY KEY,
data jsonb NOT NULL
);
INSERT INTO mytable (data)
VALUES
(
'{ "name": "foo", "tel": "123"}'
);
update mytable
set data = jsonb_insert(data, '{new_info, b}', '"baz"')
where data @> '{"name": "foo"}'
returning *;
Так что для меня это немного удивительно, так как создается впечатление, что оно спасло, хотя и не спасло. Я хочу избегать операторов case, поскольку в большинстве случаев это будет ненужной проверкой, и скорее всего она провалится, если «new_info» не существует (или просто создаст ее, если она не добавляет накладных расходов в ситуациях, когда «new_info» уже существует). существовать). Т.е. я хочу избежать того, что делают эти ответы:
Проверить, существует ли ключ в JSON с PL / pgSQL?
Обновление или создание вложенного значения jsonb с помощью одной команды обновления