Как обновить любое поле в json типа json? Он должен принять объект или массив ключей и обновить ключ, если он существует, иначе создайте

#sql #node.js #json #postgresql

Вопрос:

Универсальная функция в nodejs и Postgres для обновления ключа в столбце JSON типа JSON в Postgres.

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

 update contacts set contact_data = jsonb_set(contact_data, '{order_id}', '${order_date}', '${product_name}') where id = ${id};
 

Но проблема в том, что каждый раз мне нужно указывать ключи. Мне нужно что-то общее, что-то, что принимает набор ключей и обновляет их. Клавиши могут меняться при каждом вызове функции.

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

Пожалуйста, дайте мне знать, если вам нужны дополнительные разъяснения по этому вопросу. Спасибо.

Комментарии:

1. Что не является общим в этом утверждении?

2. Каждый раз, когда мне нужно обновить новый ключ, мне нужно добавить его в запрос, что приведет к изменению функции и запроса. Я хочу избежать этого.

3. Используйте параметр для ключа.

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

5. Да, но если мы хотим обновить несколько ключей, тогда? Ключи (и их номера) могут варьироваться.

Ответ №1:

Это решение преобразует данные jsonb в текст, чтобы быть независимым от структуры данных jsonb :

Вы передаете функции jsonb_key_replace массив старых ключей, который будет заменен массивом новых ключей. Функция jsonb_key_replace выполняет итерацию агрегатной функции replace_agg, и результат преобразуется в jsonb :

 CREATE OR REPLACE FUNCTION replace(str1 text, str2 text, old text, new text)
RETURNS text LANGUAGE sql IMMUTABLE AS
$
SELECT replace(COALESCE(str1,str2), old, new) ;
$ ;

DROP AGGREGATE IF EXISTS replace_agg (text, text, text) ;
CREATE AGGREGATE replace_agg (text, text, text)
( sfunc = replace
, stype = text
) ;

CREATE OR REPLACE FUNCTION jsonb_key_replace
( jsonb_to_update jsonb
, old_keys text[]
, new_keys text[]
)
RETURNS jsonb LANGUAGE sql IMMUTABLE AS
$
SELECT replace_agg(jsonb_to_update :: text, '"' || l.old || '":', '"' ||  l.new || '":') :: jsonb
  FROM unnest(old_key, new_key) AS l(old, new) ;
$ ;