#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) ;
$ ;