पोस्टग्रेएसक्यूएल 11+
अगर आप पहले से ही PostgreSQL v. 11 (नया JSONB
रूपांतरण समर्थन टाइप करें
) आपका सबसे अच्छा दांव शायद पर्ल या पायथन में लिखा गया एक कस्टम फ़ंक्शन होगा।
जैसा कि मैं पायथन 3 का पक्ष लेता हूं, यहां एक कार्यात्मक उदाहरण है:
CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
RETURNS jsonb
TRANSFORM FOR TYPE jsonb
LANGUAGE plpython3u
AS $$
v_new = val
tmp = v_new
for e in path_to_array:
tmp = tmp[e]
for item in tmp:
if (entry_filters is None or entry_filters.items() <= item.items()):
item.update(replacement)
return v_new
$$;
...जिसे तब निम्न प्रकार से उपयोग किया जा सकता है:
UPDATE configuration
SET
config = jsonb_replace_in_array(
config,
'{data}',
'{"value":"changed"}'::jsonb,
'{"oid":"11.5.15.1.4","instance":"1.1.4"}'::jsonb
)
WHERE config->'data' @> '[{"oid":"11.5.15.1.4","instance":"1.1.4"}]';
तो हाँ, शर्त दोहराई गई है, लेकिन केवल पहली जगह में स्पर्श करने के लिए पंक्तियों की मात्रा को सीमित करने के लिए।
वास्तव में एक सादे PostgreSQL 11 इंस्टॉलेशन पर काम करने के लिए, आपको एक्सटेंशन की आवश्यकता होती है plpython3u
और jsonb_plpython3u
:
CREATE EXTENSION plpython3u;
CREATE EXTENSION jsonb_plpython3u;
पायथन तर्क समझाया गया:
for e in path_to_array:
tmp = tmp[e]
...हमें उन प्रविष्टियों की श्रेणी में ले जाता है जिन्हें हमें देखने की आवश्यकता है।
for item in tmp:
if (entry_filters is None or entry_filters.items() <= item.items()):
item.update(replacement)
... सरणी में प्रत्येक आइटम के लिए, हम जांचते हैं कि क्या फ़िल्टर मानदंड null
है (entry_filters is None
=किसी भी प्रविष्टि से मेल खाता है) या क्या प्रविष्टि में कुंजी और मान सहित दिए गए उदाहरण "शामिल हैं" (entry_filters.items() <= item.items()
)।
यदि एन प्रविष्टि मेल खाती है, तो दिए गए प्रतिस्थापन के साथ सामग्री को अधिलेखित/जोड़ें।
मुझे आशा है कि यह उस दिशा में जाएगा जहां आप ढूंढ रहे हैं।
JSON संशोधन से संबंधित PostgreSQL की वर्तमान क्षमताओं को देखते हुए यह बहुत जटिल होगा (यदि जटिल नहीं है) और शुद्ध SQL के साथ ऐसा करने के लिए बहुत अधिक ओवरहेड पेश करेगा।
PostgreSQL 9.6+
यदि आपके पास अभी तक संस्करण 11 उपलब्ध नहीं है, तो निम्न फ़ंक्शन स्वयं प्रकार के रूपांतरणों को संभालने की कीमत पर ऐसा ही करेगा, लेकिन इसे पूरी तरह से एपीआई-संगत बनाए रखेगा, इसलिए आप एक बार अपग्रेड करने के बाद, केवल एक चीज जो आपको करनी है फ़ंक्शन को प्रतिस्थापित करता है (इस फ़ंक्शन का उपयोग करके किसी भी कथन में कोई परिवर्तन आवश्यक नहीं):
CREATE OR REPLACE FUNCTION jsonb_replace_in_array (val jsonb, path_to_array text[], replacement jsonb, entry_filters jsonb)
RETURNS jsonb
LANGUAGE plpython3u
AS $$
import json
v_new = json.loads(val)
t_replace = json.loads(replacement)
t_filters = json.loads(entry_filters)
tmp = v_new
for e in path_to_array:
tmp = tmp[e]
for item in tmp:
if (entry_filters is None or t_filters.items() <= item.items()):
item.update(t_replace)
return json.dumps(v_new)
$$;