Pembaruan : Dengan PostgreSQL 9.5 , ada beberapa jsonb
fungsi manipulasi di dalam PostgreSQL itu sendiri (tetapi tidak ada untuk json
; pemeran diperlukan untuk memanipulasi json
nilai).
Menggabungkan 2 (atau lebih) objek JSON (atau array gabungan):
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]'
Jadi, pengaturan kunci sederhana dapat dilakukan dengan menggunakan:
SELECT jsonb '{"a":1}' || jsonb_build_object('<key>', '<value>')
Di mana <key>
harus string, dan <value>
bisa apa pun jenis to_jsonb()
menerima.
Untuk mengatur nilai jauh di dalam hirarki JSON , jsonb_set()
fungsi tersebut dapat digunakan:
SELECT jsonb_set('{"a":[null,{"b":[]}]}', '{a,1,b,0}', jsonb '{"c":3}')
-- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'
Daftar parameter lengkap jsonb_set()
:
jsonb_set(target jsonb,
path text[],
new_value jsonb,
create_missing boolean default true)
path
juga bisa memuat indeks array JSON & bilangan bulat negatif yang muncul di sana terhitung dari akhir array JSON. Namun, indeks array JSON yang tidak ada, tetapi positif akan menambahkan elemen ke akhir array:
SELECT jsonb_set('{"a":[null,{"b":[1,2]}]}', '{a,1,b,1000}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}'
Untuk memasukkan ke dalam array JSON (sambil mempertahankan semua nilai asli) , jsonb_insert()
fungsi tersebut dapat digunakan ( dalam 9.6+; fungsi ini saja, di bagian ini ):
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]}]}'
Daftar parameter lengkap jsonb_insert()
:
jsonb_insert(target jsonb,
path text[],
new_value jsonb,
insert_after boolean default false)
Sekali lagi, bilangan bulat negatif yang muncul dalam path
hitungan dari akhir array JSON.
Jadi, selanjutnya menambahkan ke akhir array JSON dapat dilakukan dengan:
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
Namun, fungsi ini bekerja sedikit berbeda (dari jsonb_set()
) ketika path
in target
adalah kunci objek JSON. Dalam hal ini, itu hanya akan menambahkan pasangan nilai kunci baru untuk objek JSON ketika kunci tidak digunakan. Jika digunakan, itu akan menimbulkan kesalahan:
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
Menghapus kunci (atau indeks) dari objek JSON (atau, dari array) dapat dilakukan dengan -
operator:
SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
jsonb '["a",1,"b",2]' - 1 -- will yield jsonb '["a","b",2]'
Menghapus, dari dalam hierarki JSON dapat dilakukan dengan #-
operator:
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'
Untuk 9.4 , Anda dapat menggunakan versi modifikasi dari jawaban asli (di bawah), tetapi alih-alih menggabungkan string JSON, Anda dapat menggabungkan ke dalam objek json secara langsung json_object_agg()
.
Jawaban asli : Dimungkinkan (tanpa plpython atau plv8) dalam SQL murni juga (tetapi perlu 9.3+, tidak akan bekerja dengan 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
Edit :
Versi, yang menetapkan beberapa kunci & nilai:
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$;
Sunting 2 : seperti @ErwinBrandstetter mencatat fungsi-fungsi di atas berfungsi seperti yang disebut UPSERT
(memperbarui bidang jika ada, menyisipkan jika tidak ada). Berikut ini varian, yang hanya 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$;
Sunting 3 : Berikut adalah varian rekursif, yang dapat mengatur ( UPSERT
) nilai daun (dan menggunakan fungsi pertama dari jawaban ini), yang terletak di jalur-kunci (di mana kunci hanya bisa merujuk ke objek dalam, array dalam tidak didukung):
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$;
Perbarui : fungsi dipadatkan sekarang.
select json_object_set_key((select data from test where data->>'b' = '2'), 'b', 'two');
pesan kesalahan adalahERROR: could not determine polymorphic type because input has type "unknown"
UPSERT
, bukanUPDATE
. Jika kunci belum ada di bidang json, itu ditambahkan. Lihatlah pertanyaan terkait ini untuk yang sebenarnyaUPDATE
: stackoverflow.com/questions/7711432/… (Ini untuk tipe komposit, tetapi prinsipnya mirip untuk json.)$2::text
.Dengan 9.5 gunakan jsonb_set-
di mana tubuh adalah tipe kolom jsonb.
sumber
upper
seperti itu:update objects set body=jsonb_set(body, '{name}', upper('"Mary"'), true) where id=1;
itu tidak mengenali, atau bagaimana saya bisa mencapai perilaku yang sama? thxDengan Postgresql 9.5 dapat dilakukan dengan mengikuti-
ATAU
Seseorang bertanya bagaimana memperbarui banyak bidang dalam nilai jsonb sekaligus. Misalkan kita membuat tabel:
Lalu kami menyisipkan baris eksperimental:
Lalu kami MEMPERBARUI baris:
Yang melakukan hal berikut:
Memilih data:
Akan menghasilkan:
Untuk memperbarui bidang di dalam, Jangan gunakan operator khusus
||
. Gunakan jsonb_set sebagai gantinya. Yang tidak sederhana:Menggunakan operator concat untuk {c, c1} misalnya:
Akan menghapus {c, c2} dan {c, c3}.
Untuk kekuatan lebih, cari kekuatan di dokumentasi fungsi json postgresql . Seseorang mungkin tertarik pada
#-
operator,jsonb_set
fungsi dan jugajsonb_insert
fungsi.sumber
UPDATE users SET profile = profile || '{"lastname":"Washington"}' WHERE profile->>'name' = 'George Washington';
Untuk membangun berdasarkan jawaban @ pozs, berikut adalah beberapa fungsi PostgreSQL lainnya yang mungkin berguna bagi sebagian orang. (Membutuhkan PostgreSQL 9.3+)
Hapus Dengan Kunci: Menghapus nilai dari struktur JSON dengan kunci.
Hapus Rekursif Dengan Kunci: Menghapus nilai dari struktur JSON oleh jalur-kunci. (membutuhkan
json_object_set_key
fungsi @ pozs )Contoh penggunaan:
sumber
Ini sepertinya bekerja pada PostgreSQL 9.5
sumber
Jika jenis bidang Anda adalah json, maka yang berikut ini akan berfungsi untuk Anda.
Operator '-' menghapus kunci / pasangan nilai atau elemen string dari operan kiri. Pasangan kunci / nilai dicocokkan berdasarkan nilai kunci mereka.
Operator '||' menggabungkan dua nilai jsonb menjadi nilai jsonb baru.
Karena ini adalah operator jsonb, Anda hanya perlu mengetikkan ke :: jsonb
Info lebih lanjut: Fungsi dan Operator JSON
Anda dapat membaca catatan saya di sini
sumber
Dengan PostgreSQL 9.4, kami telah mengimplementasikan fungsi python berikut. Mungkin juga bekerja dengan PostgreSQL 9.3.
Contoh penggunaan:
Perhatikan bahwa untuk majikan sebelumnya, saya telah menulis satu set fungsi C untuk memanipulasi data JSON sebagai teks (bukan sebagai
json
ataujsonb
jenis) untuk PostgreSQL 7, 8 dan 9. Misalnya, mengekstraksi data denganjson_path('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']')
, mengatur data denganjson_path_set('{"obj":[12, 34, {"num":-45.67}]}', '$.obj[2]['num']', '99.87')
dan sebagainya. Butuh waktu sekitar 3 hari kerja, jadi jika Anda perlu menjalankannya pada sistem lama dan punya waktu luang, mungkin sepadan dengan usaha. Saya membayangkan versi C jauh lebih cepat daripada versi python.sumber
Meskipun yang berikut tidak akan memenuhi permintaan ini (fungsi json_object_agg tidak tersedia di PostgreSQL 9.3), yang berikut ini dapat bermanfaat bagi siapa saja yang mencari || operator untuk PostgreSQL 9.4, sebagaimana diterapkan dalam PostgreSQL 9.5 mendatang:
sumber
Saya menulis fungsi kecil untuk diri saya sendiri yang bekerja secara rekursif di Postgres 9.4. Inilah fungsinya (saya harap ini berfungsi dengan baik untuk Anda):
Berikut ini contoh penggunaannya:
Seperti yang Anda lihat itu menganalisis dalam-dalam dan memperbarui / menambah nilai jika diperlukan.
sumber
Ini berfungsi untuk saya, ketika mencoba memperbarui bidang tipe string.
Semoga ini bisa membantu orang lain!
Mengasumsikan table table_name memiliki kolom jsonb bernama body dan Anda ingin mengubah body.some_key = 'value'
sumber
Sayangnya, saya belum menemukan apa pun di dokumentasi, tetapi Anda dapat menggunakan beberapa solusi, misalnya Anda dapat menulis beberapa fungsi tambahan.
Misalnya, dalam Python:
lalu
sumber
value
juga akan memerlukanloads
ketika mengatur nilai-nilai non numerik seperti string (js[key] = loads(value)
) - Jika tidak:select json_update('{"a":"a"}', 'a', to_json('b')); -> {"a": "\"b\""}
Cuplikan plpython berikut mungkin berguna.
sumber
Saya menemukan jawaban sebelumnya adalah pengguna PostgreSQL berpengalaman yang cocok, maka jawaban saya:
Asumsikan Anda memiliki kolom-tabel tipe JSONB dengan nilai berikut:
mari kita asumsikan kita ingin menetapkan nilai baru di baris:
dan sebagai gantinya letakkan nilainya:
kita menggunakan fungsi json_set () untuk menetapkan nilai baru ke key13
parameter ke jsonb_set ()
di " target " - Saya akan menempatkan nama kolom jsonb (ini adalah kolom tabel yang sedang dimodifikasi)
" path " - adalah "path json keys" yang mengarah ke (dan termasuk) kunci yang akan kita timpa
" new_value " - ini adalah nilai baru yang kami berikan
dalam kasus kami, kami ingin memperbarui nilai key13 yang berada di bawah key1 (key1 -> key13):
maka sintaks pathnya adalah: '{key1, key13}' (Path adalah bagian yang paling sulit untuk diretas - karena tutorialnya sangat buruk)
sumber
Anda juga dapat menambahkan kunci secara atomis dalam
jsonb
seperti ini:Kunci tidak terdefinisi -> mengasumsikan nilai awal 0.
Untuk penjelasan lebih rinci, lihat jawaban saya di sini: https://stackoverflow.com/a/39076637
sumber
Bagi yang menggunakan
mybatis
, berikut adalah contoh pernyataan pembaruan:Params:
qid
, kunci untuk bidang.value
, adalah string json yang valid, untuk nilai bidang,misalnya dikonversi dari objek ke string json via
jackson
,sumber
Jadi, misalnya string saya terlihat seperti ini: {"a1": {"a11": "x", "a22": "y", "a33": "z"}}
Saya memperbarui jsons dengan menggunakan tabel temp, yang cukup bagus untuk jumlah data yang sedikit (<1.000.000). Saya menemukan cara yang berbeda, tetapi kemudian pergi berlibur dan melupakannya ...
Begitu. kueri akan menjadi seperti ini:
Ini lebih banyak berkaitan dengan string daripada json, tetapi ia bekerja. Pada dasarnya, ini menarik semua data ke tabel temp, membuat string sambil mencolokkan lubang-lubang concat dengan data yang Anda buat cadangannya, dan mengubahnya menjadi jsonb.
Json_set mungkin lebih efisien, tapi saya masih bisa menguasainya. Pertama kali saya mencoba menggunakannya, saya mengacaukan string sepenuhnya ...
sumber
Jika Anda membuat kueri ini dengan klien bahasa pemrograman, misalnya dari
python pycopg2
, atauNode Postgres
, Pastikan Anda mengurai data baru ke JSON terlebih dahulu.Mungkin dengan mudah terlihat seperti kamus python adalah Sama seperti objek JSON tetapi tidak terlebih dahulu melakukan json.dumps pada kamus.
Cuplikan python sederhana:
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()
sumber