Хотя это возможно с крайне нечитаемым запросом, функция PostgreSQL jsonb_set
не (пока) не может использовать JSONPath для выбора элемента для замены, но незавершенное выполнение связано с эта тема .
В настоящее время, вероятно, лучше написать вспомогательную функцию.
Поскольку я предпочитаю Python, вот мое мнение (достаточно общее, чтобы поддерживать различныесценарии, но достаточно адаптированные, чтобы их нельзя было использовать):
CREATE OR REPLACE FUNCTION jsonb_change_setting(val jsonb, segment_filter jsonb, setting text, replacement jsonb)
RETURNS jsonb
TRANSFORM FOR TYPE jsonb
LANGUAGE plpython3u
AS $$
v_new = val
tmp = v_new["segments"]
for item in tmp:
if (segment_filter.items() <= item.items()):
settings = item["settings"]
for s in settings:
if (s["name"] == setting):
s["value"] = replacement
return v_new
$$;
... и могут быть вызваны следующим образом для вашего требования:
UPDATE serial_rules
SET rule = jsonb_change_setting(config, '{"type":"autoIncrement"}', 'period', '"forever"')
WHERE ...
Помните, что для этой функции требуется PostgreSQL 11 и расширенияplpython3u и jsonb_plpython3u (для автоматической обработки jsonb).
Версия для PostgreSQL 9.6+ (где расширение преобразователя типа jsonb_plpython3u
недоступно) будет:
CREATE OR REPLACE FUNCTION jsonb_change_setting(val jsonb, segment_filter jsonb, setting text, replacement jsonb)
RETURNS jsonb
LANGUAGE plpython3u
AS $$
import json
v_new = json.loads(val)
tmp = v_new["segments"]
for item in tmp:
if (segment_filter.items() <= item.items()):
settings = item["settings"]
for s in settings:
if (s["name"] == setting):
s["value"] = replacement
return json.dumps(v_new)
$$;