আমি কীভাবে নতুন পোস্টগ্রিজ এসকিউএল জেএসএন ডেটাটাইপের অভ্যন্তরে ক্ষেত্রগুলি সংশোধন করব?


235

Postgresql 9.3 দিয়ে আমি একটি JSON ডেটা ধরণের নির্দিষ্ট ক্ষেত্রগুলি নির্বাচন করতে পারি, তবে আপনি কীভাবে আপডেটগুলি ব্যবহার করে সেগুলিকে সংশোধন করবেন? পোস্টগ্রিস্কল ডকুমেন্টেশনে বা অনলাইনে কোথাও এর কোনও উদাহরণ আমি পাই না। আমি স্পষ্ট চেষ্টা করেছি:

postgres=# create table test (data json);
CREATE TABLE
postgres=# insert into test (data) values ('{"a":1,"b":2}');
INSERT 0 1
postgres=# select data->'a' from test where data->>'b' = '2';
 ?column?
----------
 1
(1 row)
postgres=# update test set data->'a' = to_json(5) where data->>'b' = '2';
ERROR:  syntax error at or near "->"
LINE 1: update test set data->'a' = to_json(5) where data->>'b' = '2...

উত্তর:


330

আপডেট : পোস্টগ্রেএসকিউএল 9.5 এর সাথে পোস্টগ্র্রেএসকিউএলjsonb নিজেই কিছু হেরফের কার্যকারিতা রয়েছে (তবে এর জন্য কিছুই নয় json; বর্ণকে jsonমানগুলি হস্তান্তর করার প্রয়োজন হয় না )।

2 (বা আরও) জেএসওএন অবজেক্টগুলিকে মার্জ করা (বা কনটেনেটিং অ্যারে):

SELECT jsonb '{"a":1}' || jsonb '{"b":2}', -- will yield jsonb '{"a":1,"b":2}'
       jsonb '["a",1]' || jsonb '["b",2]'  -- will yield jsonb '["a",1,"b",2]'

সুতরাং, একটি সাধারণ কী নির্ধারণ করে ব্যবহার করা যেতে পারে:

SELECT jsonb '{"a":1}' || jsonb_build_object('<key>', '<value>')

<key>স্ট্রিংটি কোথায় হওয়া উচিত এবং <value>যে কোনও ধরণের to_jsonb()গ্রহণযোগ্য হতে পারে ।

একটি JSON শ্রেণিবিন্যাসের গভীরতম মান নির্ধারণের জন্য , jsonb_set()ফাংশনটি ব্যবহার করা যেতে পারে:

SELECT jsonb_set('{"a":[null,{"b":[]}]}', '{a,1,b,0}', jsonb '{"c":3}')
-- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'

সম্পূর্ণ পরামিতি তালিকা jsonb_set():

jsonb_set(target         jsonb,
          path           text[],
          new_value      jsonb,
          create_missing boolean default true)

pathJSON অ্যারে সূচকগুলিও খুব বেশি থাকতে পারে এবং নেতিবাচক পূর্ণসংখ্যার উপস্থিতিগুলি JSON অ্যারেগুলির শেষে থেকে গণনা করা হয়। তবে একটি অস্তিত্বহীন, তবে ইতিবাচক জেএসওএন অ্যারে সূচক উপাদানটিকে অ্যারের শেষে যুক্ত করবে:

SELECT jsonb_set('{"a":[null,{"b":[1,2]}]}', '{a,1,b,1000}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}'

জন্য তাদেরকে JSON অ্যারের মধ্যে ঢোকাতে (মূল মূল্যবোধের সব সংরক্ষণের সময়) , jsonb_insert()(ফাংশন ব্যবহার করা যেতে পারে 9.6+ মধ্যে; শুধুমাত্র এই বিভাগে এই ফাংশন, ):

SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2')
-- will yield jsonb '{"a":[null,{"b":[2,1]}]}', and
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2', true)
-- will yield jsonb '{"a":[null,{"b":[1,2]}]}'

সম্পূর্ণ পরামিতি তালিকা jsonb_insert():

jsonb_insert(target       jsonb,
             path         text[],
             new_value    jsonb,
             insert_after boolean default false)

আবার, নেতিবাচক পূর্ণসংখ্যাগুলি যা pathJSON অ্যারেগুলির শেষে থেকে গণনাতে উপস্থিত হয় ।

সুতরাং, f.ex. একটি JSON অ্যারে শেষ সংযোজন এর মাধ্যমে করা যেতে পারে:

SELECT jsonb_insert('{"a":[null,{"b":[1,2]}]}', '{a,1,b,-1}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}', and

যাইহোক, এই ফাংশন সামান্য ভিন্নভাবে (তুলনায় কাজ করছে jsonb_set()) যখন pathমধ্যে targetএকটি JSON- বস্তুর চাবিকাঠি। সেক্ষেত্রে, কীটি ব্যবহার না করা হলে এটি কেবল JSON অবজেক্টের জন্য একটি নতুন কী-মান জুটি যুক্ত করবে। যদি এটি ব্যবহার করা হয় তবে এটি একটি ত্রুটি বাড়িয়ে তুলবে:

SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,c}', jsonb '[2]')
-- will yield jsonb '{"a":[null,{"b":[1],"c":[2]}]}', but
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b}', jsonb '[2]')
-- will raise SQLSTATE 22023 (invalid_parameter_value): cannot replace existing key

একটি JSON অবজেক্ট (বা একটি অ্যারে থেকে ) থেকে একটি কী (বা একটি সূচক) মুছে ফেলা- অপারেটরের মাধ্যমে করা যেতে পারে :

SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
       jsonb '["a",1,"b",2]' - 1    -- will yield jsonb '["a","b",2]'

একটি JSON- শ্রেণীবিন্যাসে গভীর থেকে মুছে ফেলা হচ্ছে সঙ্গে কাজ করা যেতে পারে #-অপারেটর:

SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'

9.4-র জন্য , আপনি মূল উত্তরের (নীচে) একটি সংশোধিত সংস্করণ ব্যবহার করতে পারেন, তবে কোনও জেএসএন স্ট্রিংকে একত্রিত করার পরিবর্তে আপনি সরাসরি একটি জসন অবজেক্টে একত্রিত করতে পারেন json_object_agg()

মূল উত্তর : খাঁটি এসকিউএলে এটিও সম্ভব (পলপিথন বা plv8 ছাড়াই) সম্ভব (তবে 9.3+ প্রয়োজন, 9.2 দিয়ে কাজ করবে না)

CREATE OR REPLACE FUNCTION "json_object_set_key"(
  "json"          json,
  "key_to_set"    TEXT,
  "value_to_set"  anyelement
)
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
  FROM (SELECT *
          FROM json_each("json")
         WHERE "key" <> "key_to_set"
         UNION ALL
        SELECT "key_to_set", to_json("value_to_set")) AS "fields"
$function$;

SQLFiddle

সম্পাদনা করুন :

একটি সংস্করণ, যা একাধিক কী এবং মান সেট করে:

CREATE OR REPLACE FUNCTION "json_object_set_keys"(
  "json"          json,
  "keys_to_set"   TEXT[],
  "values_to_set" anyarray
)
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
  FROM (SELECT *
          FROM json_each("json")
         WHERE "key" <> ALL ("keys_to_set")
         UNION ALL
        SELECT DISTINCT ON ("keys_to_set"["index"])
               "keys_to_set"["index"],
               CASE
                 WHEN "values_to_set"["index"] IS NULL THEN 'null'::json
                 ELSE to_json("values_to_set"["index"])
               END
          FROM generate_subscripts("keys_to_set", 1) AS "keys"("index")
          JOIN generate_subscripts("values_to_set", 1) AS "values"("index")
         USING ("index")) AS "fields"
$function$;

2 সম্পাদনা করুন : @ এরউইন ব্র্যান্ডস্টেটর উপরে উল্লিখিত এই ফাংশনগুলিকে তথাকথিত হিসাবে কাজ করেছে UPSERT(একটি ক্ষেত্র যদি এটি উপস্থিত থাকে তবে এটি উপস্থিত না থাকলে সন্নিবেশ করায় আপডেট করে) noted এখানে একটি বৈকল্পিক রয়েছে যা কেবলমাত্র UPDATE:

CREATE OR REPLACE FUNCTION "json_object_update_key"(
  "json"          json,
  "key_to_set"    TEXT,
  "value_to_set"  anyelement
)
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT CASE
  WHEN ("json" -> "key_to_set") IS NULL THEN "json"
  ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')
          FROM (SELECT *
                  FROM json_each("json")
                 WHERE "key" <> "key_to_set"
                 UNION ALL
                SELECT "key_to_set", to_json("value_to_set")) AS "fields")::json
END
$function$;

3 সম্পাদনা করুন : এখানে পুনরাবৃত্তিমূলক বৈকল্পিক রয়েছে, যা UPSERTএকটি কী-পাথ (যেখানে কীগুলি কেবল অভ্যন্তরীণ বস্তুগুলিকে বোঝাতে পারে, অভ্যন্তরীণ অ্যারে সমর্থিত নয়) অবস্থিত একটি পাতার মান নির্ধারণ করতে পারে (এবং এই উত্তর থেকে প্রথম ফাংশন ব্যবহার করে):

CREATE OR REPLACE FUNCTION "json_object_set_path"(
  "json"          json,
  "key_path"      TEXT[],
  "value_to_set"  anyelement
)
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT CASE COALESCE(array_length("key_path", 1), 0)
         WHEN 0 THEN to_json("value_to_set")
         WHEN 1 THEN "json_object_set_key"("json", "key_path"[l], "value_to_set")
         ELSE "json_object_set_key"(
           "json",
           "key_path"[l],
           "json_object_set_path"(
             COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
             "key_path"[l+1:u],
             "value_to_set"
           )
         )
       END
  FROM array_lower("key_path", 1) l,
       array_upper("key_path", 1) u
$function$;

আপডেট : ফাংশন এখন সংক্ষিপ্ত করা হয়।


5
আমি আপনার plpgsql ফাংশনটি চেষ্টা করেছিলাম, তবে এটি কীভাবে ব্যবহার করতে হবে তা সম্পর্কে নিশ্চিত নই - আমি select json_object_set_key((select data from test where data->>'b' = '2'), 'b', 'two'); ত্রুটি বার্তাটি চেষ্টা করার সময় একটি ত্রুটি দেখছিERROR: could not determine polymorphic type because input has type "unknown"
user9645

1
এটি একটি UPSERTনয়, একটি এর সমতুল্য সম্পাদন করে UPDATE। কীটি এখনও জসন ক্ষেত্রে উপস্থিত না থাকলে এটি যুক্ত করা হয়। এই সম্পর্কিত প্রশ্নটির জন্য প্রকৃত দিকে তাকান UPDATE: স্ট্যাকওভারফ্লো / প্রশ্ন / 1111১১৪৩২/২ (এটি একটি যৌগিক প্রকারের জন্য, তবে
প্রধানটি জসনের

1
@ এরউইন ব্র্যান্ডসেটেটারটি সত্য, তবে জসনে একটি ইউপিএসআরটি সাধারণত একটি আপডেটের মতো পরিবর্তনের চেয়ে বেশি সাধারণ হয় (f.ex. sqlfiddle.com/#!15/d41d8/2897 বিবেচনা করুন ) - আপনি কীভাবে সংশোধন করবেন আমি মূল প্রশ্নের ব্যাখ্যা করেছি তাদের (জসন কলাম) একটি আপডেটের বিবৃতি ব্যবহার করে? - একক শর্ত ছাড়াও এটি আপডেটে রূপান্তর করতে পারে।
'40-এ পোজ দিন s

1
এখন খুব দরকারী এবং সম্পূর্ণ।
এরউইন ব্র্যান্ডসটেটার

1
@ ম্যাক্সহড যা ক্লায়েন্টের উপর নির্ভর করে (বা আপনি যে ক্লায়েন্ট লাইব্রেরি ব্যবহার করেন)। যদি আপনি পারেন তবে সুস্পষ্ট প্রকারগুলি ব্যবহার করুন (পোস্টগ্রাইএসকিউএল প্যারামেট্রাইজড কোয়েরিতে প্রকারগুলি অনুমান করতে পারে তবে এটি পলিমারফিক ফাংশনগুলির সাথে সাধারণত ভাল কাজ করে না)। তবে কমপক্ষে, আপনি সুস্পষ্ট কাস্ট ব্যবহার করতে পারেন, পছন্দ করুন $2::text
এজেজ

98

9.5 ব্যবহার করে jsonb_set-

UPDATE objects
SET body = jsonb_set(body, '{name}', '"Mary"', true)
WHERE id = 1; 

যেখানে শরীরটি একটি জাসনব কলামের ধরণ।


হাই, আমি কেন এটি ব্যবহার করতে পারি না upper: update objects set body=jsonb_set(body, '{name}', upper('"Mary"'), true) where id=1;এটি স্বীকৃতি দেয় না বা আমি কীভাবে একই আচরণ করতে পারি? thx
রাফায়েল ক্যাপুচো

1
আমি যে মানটি সেট করতে চাই তা যদি "মেরি" এর পরিবর্তে অন্য কলামের একটি স্ট্রিং থাকে তবে আমি কীভাবে এটি করব?
অ্যান্ড্রু

58

Postgresql 9.5 এর সাহায্যে এটি অনুসরণ করে করা যেতে পারে-

UPDATE test
SET data = data - 'a' || '{"a":5}'
WHERE data->>'b' = '2';

অথবা

UPDATE test
SET data = jsonb_set(data, '{a}', '5'::jsonb);

কেউ জিজ্ঞাসা করেছিল যে কীভাবে একবারে jsonb মানগুলিতে অনেকগুলি ক্ষেত্র আপডেট করা যায়। মনে করুন আমরা একটি টেবিল তৈরি করেছি:

CREATE TABLE testjsonb ( id SERIAL PRIMARY KEY, object JSONB );

তারপরে আমরা একটি পরীক্ষামূলক সারিটি লিখি:

INSERT INTO testjsonb
VALUES (DEFAULT, '{"a":"one", "b":"two", "c":{"c1":"see1","c2":"see2","c3":"see3"}}');

তারপরে আমরা সারিটি আপডেট করব:

UPDATE testjsonb SET object = object - 'b' || '{"a":1,"d":4}';

যা নিম্নলিখিতগুলি করে:

  1. ক্ষেত্র আপডেট করে
  2. খ ক্ষেত্রটি সরিয়ে দেয়
  3. ডি ক্ষেত্র যোগ করুন

ডেটা নির্বাচন করা হচ্ছে:

SELECT jsonb_pretty(object) FROM testjsonb;

ফলাফল হবে:

      jsonb_pretty
-------------------------
 {                      +
     "a": 1,            +
     "c": {             +
         "c1": "see1",  +
         "c2": "see2",  +
         "c3": "see3",  +
     },                 +
     "d": 4             +
 }
(1 row)

ভিতরে ক্ষেত্রটি আপডেট করতে, কনক্যাট অপারেটরটি ব্যবহার করবেন না || । পরিবর্তে jsonb_set ব্যবহার করুন। কোনটি সহজ নয়:

UPDATE testjsonb SET object =
jsonb_set(jsonb_set(object, '{c,c1}','"seeme"'),'{c,c2}','"seehim"');

Conc c, c1 for এর জন্য কনক্যাট অপারেটর ব্যবহার করে উদাহরণস্বরূপ:

UPDATE testjsonb SET object = object || '{"c":{"c1":"seedoctor"}}';

{C, c2} এবং {c, c3 remove মুছে ফেলবে}

আরও শক্তির জন্য, পোস্টগ্র্যাস্কল জসন ফাংশন ডকুমেন্টেশনে পাওয়ার সন্ধান করুন । এক #-অপারেটর, jsonb_setফাংশন এবং এছাড়াও jsonb_insertকাজ করতে আগ্রহী হতে পারে ।


এবং যদি আমাকে দুটি ক্ষেত্র আপডেট করতে হয় তবে সিনট্যাক্সটি কী?
সুনীল গার্গ

আমার যদি ক্ষেত্রের নাম সহ একটি জসন কলাম থাকে, আমি কীভাবে এই কলামটিতে
লাস্টনাম

পরিষ্কার হওয়া উচিত:UPDATE users SET profile = profile || '{"lastname":"Washington"}' WHERE profile->>'name' = 'George Washington';
ফান্দি সুসান্টো

9

@ পোজ এর উত্তরগুলি তৈরি করতে, এখানে আরও কয়েকটি পোস্টগ্রেএসকিউএল ফাংশন রয়েছে যা কারওর পক্ষে কার্যকর হতে পারে। (পোস্টগ্রিএসকিউএল 9.3+ প্রয়োজন)

কী দ্বারা মুছুন: কী দ্বারা জেএসএন কাঠামো থেকে একটি মান মুছুন

CREATE OR REPLACE FUNCTION "json_object_del_key"(
  "json"          json,
  "key_to_del"    TEXT
)
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT CASE
  WHEN ("json" -> "key_to_del") IS NULL THEN "json"
  ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')
          FROM (SELECT *
                  FROM json_each("json")
                 WHERE "key" <> "key_to_del"
               ) AS "fields")::json
END
$function$;

কী দ্বারা পুনরাবৃত্তি মোছা: কী-পাথ দ্বারা JSON কাঠামো থেকে একটি মান মুছে দেয়। (@ পোজ এর json_object_set_keyকার্যকারিতা প্রয়োজন)

CREATE OR REPLACE FUNCTION "json_object_del_path"(
  "json"          json,
  "key_path"      TEXT[]
)
  RETURNS json
  LANGUAGE sql
  IMMUTABLE
  STRICT
AS $function$
SELECT CASE
  WHEN ("json" -> "key_path"[l] ) IS NULL THEN "json"
  ELSE
     CASE COALESCE(array_length("key_path", 1), 0)
         WHEN 0 THEN "json"
         WHEN 1 THEN "json_object_del_key"("json", "key_path"[l])
         ELSE "json_object_set_key"(
           "json",
           "key_path"[l],
           "json_object_del_path"(
             COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
             "key_path"[l+1:u]
           )
         )
       END
    END
  FROM array_lower("key_path", 1) l,
       array_upper("key_path", 1) u
$function$;

ব্যবহারের উদাহরণ:

s1=# SELECT json_object_del_key ('{"hello":[7,3,1],"foo":{"mofu":"fuwa", "moe":"kyun"}}',
                                 'foo'),
            json_object_del_path('{"hello":[7,3,1],"foo":{"mofu":"fuwa", "moe":"kyun"}}',
                                 '{"foo","moe"}');

 json_object_del_key |          json_object_del_path
---------------------+-----------------------------------------
 {"hello":[7,3,1]}   | {"hello":[7,3,1],"foo":{"mofu":"fuwa"}}

খুব দরকারী! ধন্যবাদ.
1111161171159459134

9
UPDATE test
SET data = data::jsonb - 'a' || '{"a":5}'::jsonb
WHERE data->>'b' = '2'

এটি পোস্টগ্রিসকিউএল 9.5 তে কাজ করছে বলে মনে হচ্ছে


আমার পক্ষে কাজ করে, যতদূর আমি বুঝতে পেরেছি, এটি ডেটা থেকে ক্ষেত্রটি "এ" সরিয়ে দেয় এবং তারপরে ক্ষেত্রটিকে নতুন মান সহ "ক" যুক্ত করবে। আমার ক্ষেত্রে, "ক" এর মান একটি কলামের উপর ভিত্তি করে ছিল। আপডেটের পরীক্ষা SET ডেটা = ডেটা :: জসনব - 'এ' || ('{"এ": "' || মাই কলাম || '"}') :: জসনব;
sebge2

7

আপনার ক্ষেত্রের প্রকারটি যদি জসন হয় তবে নিম্নলিখিতগুলি আপনার জন্য কাজ করবে।

UPDATE 
table_name
SET field_name = field_name::jsonb - 'key' || '{"key":new_val}' 
WHERE field_name->>'key' = 'old_value'.

অপারেটর '-' বাম অপারেণ্ড থেকে কী / মান জোড় বা স্ট্রিং উপাদান মুছুন। কী / মান জোড়াগুলি তাদের মূল মানের উপর ভিত্তি করে মিলিত হয়।

অপারেটর '||' দুটি জসনব মানকে একটি নতুন জসনব মানকে যুক্ত করুন।

যেহেতু এগুলি জসনব অপারেটর, আপনার কেবল টাইপকাস্ট করতে হবে :: জসনব

আরও তথ্য: JSON ফাংশন এবং অপারেটর

আপনি আমার নোট এখানে পড়তে পারেন


JSON ক্ষেত্রগুলি আপডেট করার সহজ ও সর্বোত্তম উপায়, যদি আপনি সম্পত্তি অর্ডার পুনর্বিন্যাস সম্পর্কে উদ্বিগ্ন না হন।
কার্তিক শিবরাজ

4

PostgreSQL 9.4 সহ, আমরা নিম্নলিখিত পাইথন ফাংশনটি প্রয়োগ করেছি। এটি PostgreSQL 9.3 এর সাথেও কাজ করতে পারে।

create language plpython2u;

create or replace function json_set(jdata jsonb, jpaths jsonb, jvalue jsonb) returns jsonb as $$
import json

a = json.loads(jdata)
b = json.loads(jpaths)

if a.__class__.__name__ != 'dict' and a.__class__.__name__ != 'list':
  raise plpy.Error("The json data must be an object or a string.")

if b.__class__.__name__ != 'list':
   raise plpy.Error("The json path must be an array of paths to traverse.")

c = a
for i in range(0, len(b)):
  p = b[i]
  plpy.notice('p == ' + str(p))

  if i == len(b) - 1:
    c[p] = json.loads(jvalue)

  else:
    if p.__class__.__name__ == 'unicode':
      plpy.notice("Traversing '" + p + "'")
      if c.__class__.__name__ != 'dict':
        raise plpy.Error("  The value here is not a dictionary.")
      else:
        c = c[p]

    if p.__class__.__name__ == 'int':
      plpy.notice("Traversing " + str(p))
      if c.__class__.__name__ != 'list':
        raise plpy.Error("  The value here is not a list.")
      else:
        c = c[p]

    if c is None:
      break    

return json.dumps(a)
$$ language plpython2u ;

ব্যবহারের উদাহরণ:

create table jsonb_table (jsonb_column jsonb);
insert into jsonb_table values
('{"cars":["Jaguar", {"type":"Unknown","partsList":[12, 34, 56]}, "Atom"]}');

select jsonb_column->'cars'->1->'partsList'->2, jsonb_column from jsonb_table;

update jsonb_table
set jsonb_column = json_set(jsonb_column, '["cars",1,"partsList",2]', '99');

select jsonb_column->'cars'->1->'partsList'->2, jsonb_column from jsonb_table;

মনে রাখবেন যে পূর্ববর্তী কোনও নিয়োগকর্তার জন্য, পোস্টগ্র্রেএসকিউএল 7, 8 এবং 9 এর জন্য আমি JSON ডেটা পাঠ্য হিসাবে (কোনও হিসাবে jsonবা jsonbটাইপ হিসাবে নয় ) ম্যানিপুলেট করার জন্য সি ফাংশনগুলির একটি সেট লিখেছি For উদাহরণস্বরূপ, এর সাথে ডেটা উত্তোলন, ডেটা json_path('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']')সেট করা json_path_set('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']', '99.87')ইত্যাদি on এটি প্রায় 3 দিনের কাজ নিয়েছে, সুতরাং আপনার যদি উত্তরাধিকার ব্যবস্থাগুলি চালানোর প্রয়োজন হয় এবং অবকাশ রাখার সময় থাকে তবে এটি প্রচেষ্টার পক্ষে মূল্যবান হতে পারে। আমি কল্পনা করি যে সি ভার্সনটি পাইথন ভার্সনের চেয়ে অনেক দ্রুত।


2

যদিও নিম্নলিখিতগুলি এই অনুরোধটি পূরণ করবে না (ফাংশন json_object_agg পোস্টগ্র্রেএসকিউএল 9.3 তে উপলভ্য নয়), নিম্নলিখিত যে কেউ অনুসন্ধানের জন্য দরকারী হতে পারে || পোস্টগ্র্রেএসকিউএল 9.4 এর জন্য অপারেটর, আসন্ন পোস্টগ্র্যাসকিউএল 9.5-তে কার্যকর হিসাবে:

CREATE OR REPLACE FUNCTION jsonb_merge(left JSONB, right JSONB)
RETURNS JSONB
AS $$
SELECT
  CASE WHEN jsonb_typeof($1) = 'object' AND jsonb_typeof($2) = 'object' THEN
       (SELECT json_object_agg(COALESCE(o.key, n.key), CASE WHEN n.key IS NOT NULL THEN n.value ELSE o.value END)::jsonb
        FROM jsonb_each($1) o
        FULL JOIN jsonb_each($2) n ON (n.key = o.key))
   ELSE 
     (CASE WHEN jsonb_typeof($1) = 'array' THEN LEFT($1::text, -1) ELSE '['||$1::text END ||', '||
      CASE WHEN jsonb_typeof($2) = 'array' THEN RIGHT($2::text, -1) ELSE $2::text||']' END)::jsonb
   END     
$$ LANGUAGE sql IMMUTABLE STRICT;
GRANT EXECUTE ON FUNCTION jsonb_merge(jsonb, jsonb) TO public;
CREATE OPERATOR || ( LEFTARG = jsonb, RIGHTARG = jsonb, PROCEDURE = jsonb_merge );

2

আমি নিজের জন্য ছোট ফাংশন লিখেছিলাম যা পোস্টগ্রিস 9.4 এ পুনরাবৃত্তভাবে কাজ করে। এখানে ফাংশনটি রয়েছে (আমি আশা করি এটি আপনার পক্ষে ভাল কাজ করে):

CREATE OR REPLACE FUNCTION jsonb_update(val1 JSONB,val2 JSONB)
RETURNS JSONB AS $$
DECLARE
    result JSONB;
    v RECORD;
BEGIN
    IF jsonb_typeof(val2) = 'null'
    THEN 
        RETURN val1;
    END IF;

    result = val1;

    FOR v IN SELECT key, value FROM jsonb_each(val2) LOOP

        IF jsonb_typeof(val2->v.key) = 'object'
            THEN
                result = result || jsonb_build_object(v.key, jsonb_update(val1->v.key, val2->v.key));
            ELSE
                result = result || jsonb_build_object(v.key, v.value);
        END IF;
    END LOOP;

    RETURN result;
END;
$$ LANGUAGE plpgsql;

নমুনা ব্যবহার এখানে:

select jsonb_update('{"a":{"b":{"c":{"d":5,"dd":6},"cc":1}},"aaa":5}'::jsonb, '{"a":{"b":{"c":{"d":15}}},"aa":9}'::jsonb);
                            jsonb_update                             
---------------------------------------------------------------------
 {"a": {"b": {"c": {"d": 15, "dd": 6}, "cc": 1}}, "aa": 9, "aaa": 5}
(1 row)

আপনি দেখতে পাচ্ছেন এটি গভীর নীচে বিশ্লেষণ করে এবং যেখানে প্রয়োজন সেখানে মানগুলি আপডেট / আপডেট করে।


2

একটি স্ট্রিং টাইপ ফিল্ড আপডেট করার চেষ্টা করার সময় এটি আমার পক্ষে কাজ করেছিল।

UPDATE table_name 
SET body = jsonb_set(body, '{some_key}', to_json('value'::TEXT)::jsonb);

আশা করি এটি অন্য কাউকে সাহায্য করবে!

সারণী টেবিলের নাম ধরে ধরে শরীরের নামের একটি জসনব কলাম রয়েছে এবং আপনি বডি পরিবর্তন করতে চান omeসুম_কি = 'মান'


দুর্ভাগ্যক্রমে এই JSON- কে JSON- নির্দিষ্ট ফাংশনগুলির মাধ্যমে ম্যানিপুলেশনের মতো একইভাবে
পুনর্বিবেচনা করেছে

1

দুঃখের বিষয়, ডকুমেন্টেশনে আমি কিছু পাইনি তবে আপনি কিছুটা ব্যবহার করতে পারেন, উদাহরণস্বরূপ আপনি কিছু বর্ধিত ফাংশন লিখতে পারেন।

উদাহরণস্বরূপ, পাইথনে:

CREATE or REPLACE FUNCTION json_update(data json, key text, value json)
returns json
as $$
from json import loads, dumps
if key is None: return data
js = loads(data)
js[key] = value
return dumps(js)
$$ language plpython3u

এবং তারপর

update test set data=json_update(data, 'a', to_json(5)) where data->>'b' = '2';

এটি লজ্জার বিষয় যে অ্যামাজন আরডিএস পিপিথথন 3 ইউ সমর্থন করে না!
dbau

2
valueআরো একটি প্রয়োজন হবে loadsযখন স্ট্রিং (যেমন অ সাংখ্যিক মান নির্ধারণের js[key] = loads(value):) - তা না হলেselect json_update('{"a":"a"}', 'a', to_json('b')); -> {"a": "\"b\""}
hooblei

এই উত্তরটি কোনও মানকে সেট করা থাকলে কী মুছে ফেলার অন্তর্ভুক্তও সংশোধন করা যেতে পারে: value মানটি কোনওটি নয়: ডেল ডেটা [কী]
জোশুয়া বার্নস

1

নিম্নলিখিত plpython স্নিপেট ব্যবহার হতে পারে।

CREATE EXTENSION IF NOT EXISTS plpythonu;
CREATE LANGUAGE plpythonu;

CREATE OR REPLACE FUNCTION json_update(data json, key text, value text)
 RETURNS json
 AS $$
    import json
    json_data = json.loads(data)
    json_data[key] = value
    return json.dumps(json_data, indent=4)
 $$ LANGUAGE plpythonu;

-- Check how JSON looks before updating

SELECT json_update(content::json, 'CFRDiagnosis.mod_nbs', '1')
FROM sc_server_centre_document WHERE record_id = 35 AND template = 'CFRDiagnosis';

-- Once satisfied update JSON inplace

UPDATE sc_server_centre_document SET content = json_update(content::json, 'CFRDiagnosis.mod_nbs', '1')
WHERE record_id = 35 AND template = 'CFRDiagnosis';

1

আমি পূর্ববর্তী উত্তরগুলি উপযুক্ত অভিজ্ঞ পোস্টগ্রিজ এসকিউএল ব্যবহারকারী হিসাবে খুঁজে পেয়েছি, সুতরাং আমার উত্তর:

ধরে নিন আপনার নীচের মান সহ JSONB প্রকারের একটি সারণী-কলাম রয়েছে:

{
    "key0": {
        "key01": "2018-05-06T12:36:11.916761+00:00",
        "key02": "DEFAULT_WEB_CONFIGURATION",

    "key1": {
        "key11": "Data System",
        "key12": "<p>Health,<p>my address<p>USA",
        "key13": "*Please refer to main screen labeling"
    }
}

ধরে নেওয়া যাক আমরা সারিতে একটি নতুন মান সেট করতে চাই:

"key13": "*Please refer to main screen labeling"

এবং পরিবর্তে মান রাখুন:

"key13": "See main screen labeling"

আমরা key13 এ নতুন মান নির্ধারণ করতে json_set () ফাংশনটি ব্যবহার করি

jsonb_set () পরামিতি

jsonb_set(target jsonb, path text[], new_value jsonb[, create_missing boolean])

মধ্যে " লক্ষ্য " এ - আমি জসনব কলাম-নাম রাখব (এটি সারণী কলামটি পরিবর্তন করা হচ্ছে)

" পথ " - হ'ল "জসন কী পাথ" যা আমরা ওভাররাইট করতে যাচ্ছি এমন কী (এবং সহ) লিডিং করে

" নতুন_মূল্য " - এটি আমরা নির্ধারিত নতুন মান

আমাদের ক্ষেত্রে আমরা কী 13 এর মান আপডেট করতে চাই যা কী 1 (কী 1 -> কী 13) এর অধীনে থাকে:

তাই পাথ সিনট্যাক্সটি হ'ল: '{কী 1, কী 13}' (পাথটি ক্র্যাক করার জন্য সবচেয়ে জটিল অংশ ছিল - কারণ টিউটোরিয়ালগুলি ভয়ঙ্কর)

jsonb_set(jsonb_column,'{key1,key13}','"See main screen labeling"')

0

আপনি jsonbএই জাতীয় মধ্যে কী কী বৃদ্ধি করতে পারেন :

UPDATE users SET counters = counters || CONCAT('{"bar":', COALESCE(counters->>'bar','0')::int + 1, '}')::jsonb WHERE id = 1;

SELECT * FROM users;

 id |    counters
----+------------
  1 | {"bar": 1}

অপরিবর্তিত কী -> 0 টির মান শুরু করে।

আরও বিশদ ব্যাখ্যার জন্য, আমার উত্তরটি এখানে দেখুন: https://stackoverflow.com/a/39076637


0

যারা ব্যবহার করেন তাদের জন্য mybatisএখানে একটি উদাহরণ আপডেটের বিবৃতি রয়েছে:

<update id="saveAnswer">
    update quiz_execution set answer_data = jsonb_set(answer_data, concat('{', #{qid}, '}')::text[], #{value}::jsonb), updated_at = #{updatedAt}
    where id = #{id}
</update>


প্যারাম:

  • qid, ক্ষেত্রের জন্য কী।
  • valueক্ষেত্রের মানের জন্য, একটি বৈধ জেএসন স্ট্রিং,
    উদাহরণস্বরূপ , অবজেক্ট থেকে জসন স্ট্রিংয়ের মাধ্যমে রূপান্তরিত jackson,

0

সুতরাং, উদাহরণস্বরূপ আমার স্ট্রিংটি এর মতো দেখাচ্ছে: {"a1": {"a11": "x", "a22": "y", "a33": "z"}}

আমি টেম্প টেবিল ব্যবহার করে জসনগুলি আপডেট করি যা ডেটা (<1.000.000) এর চেয়ে ছোট পরিমাণের জন্য যথেষ্ট ভাল। আমি অন্যভাবে খুঁজে পেয়েছি, কিন্তু তারপরে ছুটিতে গিয়ে তা ভুলে গিয়েছি ...

So. ক্যোয়ারীটি এরকম কিছু হবে:

with temp_table as (
select 
a.id,
a->'a1'->>'a11' as 'a11',
a->'a1'->>'a22' as 'a22',
a->'a1'->>'a33' as 'a33',
u1.a11updated
from foo a
join table_with_updates u1 on u1.id = a.id)
    update foo a
    set a = ('{"a1": {"a11": "'|| t.a11updated ||'",
        "a22":"'|| t.a22 ||'",
        "a33":"'|| t.a33 ||'"}}')::jsonb
    from temp_table t
    where t.id = a.id;

এটি জসনের চেয়ে স্ট্রিংয়ের সাথে আরও অনেক কিছু করতে পারে তবে এটি কাজ করে। মূলত, এটি সমস্ত ডেটা টেম্প টেবিলের দিকে টেনে তোলে, আপনার ব্যাক আপ হওয়া ডেটা সহ কনট্যাট হোলগুলি প্লাগ করার সময় একটি স্ট্রিং তৈরি করে এবং এটিকে জসনবতে রূপান্তরিত করে।

জসন_সেট আরও কার্যকর হতে পারে তবে আমি এখনও এটির একটি ঝুলন্ত। প্রথমবার এটি ব্যবহার করার চেষ্টা করার পরে আমি স্ট্রিংটি পুরোপুরি গণ্ডগোল করে দিয়েছি ...


1
হাই এবং স্ট্যাকওভারফ্লোতে আপনাকে স্বাগতম! মনে রাখবেন যে এই প্রশ্নের ইতিমধ্যে একটি স্বীকৃত উত্তর রয়েছে।
হংসসি

-2

আপনি যদি কোনও প্রোগ্রামিং ভাষার ক্লায়েন্টের সাথে এই ক্যোয়ারী তৈরি করে থাকেন, যেমন থেকে python pycopg2, বা Node Postgres, আপনি নতুন JSON এ নতুন ডেটা পার্স করার বিষয়টি নিশ্চিত করুন।

এটি সহজেই দেখতে পারে অজগর অভিধানটি জেএসওএন অবজেক্ট হিসাবে একই তবে এটি অভিধানে প্রথমে জসন.ডম্পস করে না।

একটি সাধারণ অজগর স্নিপেট:

def change_destination(self,parcel_id,destlatlng): query="UPDATE parcels SET destlatlng = '{}' WHERE parcel_id ={};".format(json.dumps(destlatlng), parcel_id) self.cursor.execute(query2) self.connection.commit()

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.