Idealnya, Anda tidak menggunakan dokumen JSON untuk data reguler terstruktur yang ingin Anda manipulasi di dalam basis data relasional. Gunakan desain relasional yang dinormalisasi sebagai gantinya.
JSON terutama dimaksudkan untuk menyimpan seluruh dokumen yang tidak perlu dimanipulasi di dalam RDBMS. Terkait:
Memperbarui baris di Postgres selalu menulis versi baru dari keseluruhan baris. Itulah prinsip dasar model MVCC Postgres . Dari perspektif kinerja, hampir tidak masalah apakah Anda mengubah satu bagian data di dalam objek JSON atau semuanya: versi baru dari baris harus ditulis.
Demikian saran dalam manual :
Data JSON tunduk pada pertimbangan kontrol-konkurensi yang sama seperti tipe data lainnya saat disimpan dalam sebuah tabel. Meskipun menyimpan dokumen besar dapat dilakukan, perlu diingat bahwa setiap pembaruan memperoleh kunci tingkat baris di seluruh baris. Pertimbangkan membatasi dokumen JSON ke ukuran yang dapat dikelola untuk mengurangi pertikaian kunci di antara memperbarui transaksi. Idealnya, dokumen JSON masing-masing harus mewakili datum atom yang mendikte aturan bisnis tidak dapat dibagi lagi menjadi datum yang lebih kecil yang dapat dimodifikasi secara independen.
Inti dari itu: untuk memodifikasi apa pun di dalam objek JSON, Anda harus menetapkan objek yang dimodifikasi ke kolom. Postgres memasok sarana terbatas untuk membuat dan memanipulasi json
data selain kemampuan penyimpanannya. Gudang peralatan telah tumbuh secara substansial dengan setiap rilis baru sejak versi 9.2. Tetapi prinsipnya tetap: Anda selalu harus menetapkan objek yang dimodifikasi lengkap ke kolom dan Postgres selalu menulis versi baris baru untuk setiap pembaruan.
Beberapa teknik cara bekerja dengan alat Postgres 9.3 atau yang lebih baru:
Jawaban ini telah menarik downvotes sebanyak semua jawaban saya yang lain pada SO bersama-sama . Orang-orang tampaknya tidak menyukai gagasan itu: desain yang dinormalisasi lebih unggul untuk data yang tidak dinamis. Posting blog yang luar biasa ini oleh Craig Ringer menjelaskan lebih terinci:
Erwin Brandstetter
sumber
json
danjsonb
sama. Keduanya menyimpan data JSON,jsonb
apakah itu dalam bentuk biner yang dinormalisasi yang memiliki beberapa kelebihan (dan sedikit kerugian). stackoverflow.com/a/10560761/939860 Tidak ada tipe data yang baik untuk memanipulasi banyak di dalam database. Tidak ada tipe dokumen. Yah, tidak masalah untuk dokumen JSON yang kecil dan sulit terstruktur. Tapi dokumen bersarang yang besar akan menjadi kebodohan seperti itu.Jika Anda dapat memutakhirkan ke Postgresql 9.5,
jsonb_set
perintah itu tersedia, seperti yang disebutkan orang lain.Dalam setiap pernyataan SQL berikut, saya telah menghilangkan
where
klausa untuk singkatnya; jelas, Anda ingin menambahkan itu kembali.Perbarui nama:
Ganti tag (sebagai lawan menambahkan atau menghapus tag):
Mengganti tag kedua (0-diindeks):
Tambahkan tag (
ini akan berfungsi selama ada kurang dari 999 tag; mengubah argumen 999 ke 1000 atau lebih menghasilkan kesalahan. Ini tidak lagi menjadi kasus di Postgres 9.5.3; indeks yang jauh lebih besar dapat digunakan) :Hapus tag terakhir:
Pembaruan kompleks (hapus tag terakhir, masukkan tag baru, dan ubah nama):
Penting untuk dicatat bahwa dalam setiap contoh ini, Anda tidak benar-benar memperbarui satu bidang data JSON. Alih-alih, Anda membuat versi data sementara yang dimodifikasi, dan menetapkan versi yang diubah itu kembali ke kolom. Dalam praktiknya, hasilnya harus sama, tetapi mengingat hal ini harus membuat pembaruan yang kompleks, seperti contoh terakhir, lebih dapat dimengerti.
Dalam contoh kompleks, ada tiga transformasi dan tiga versi sementara: Pertama, tag terakhir dihapus. Kemudian, versi itu diubah dengan menambahkan tag baru. Selanjutnya, versi kedua ditransformasikan dengan mengubah
name
bidang. Nilai dalamdata
kolom diganti dengan versi final.sumber
jsonb_set
panggilan luar adalah output dari panggilan dalam, dan bahwa input ke panggilan dalam adalah hasil daridata #- '{tags,-1}'
. Yaitu, data asli dengan tag terakhir dihapus.{tags,0}
, itu berarti "elemen pertama arraytags
", yang memungkinkan saya untuk memberikan nilai baru pada elemen itu. Dengan menggunakan angka besar alih-alih 0, alih-alih mengganti elemen yang ada dalam array, ia menambahkan elemen baru ke array. Namun, jika array sebenarnya memiliki lebih dari 999.999.999 elemen di dalamnya, ini akan menggantikan elemen terakhir alih-alih menambahkan yang baru.Ini datang dalam 9,5 dalam bentuk jsonb_set oleh Andrew Dunstan berdasarkan ekstensi jsonbx yang ada yang bekerja dengan 9,4
sumber
jsonb_build_object()
, karenax->key
, tidak mengembalikan pasangan objek-kunci, untuk mengisi yang Anda butuhkanjsonb_set(target, path, jsonb_build_object('key',x->key))
.Bagi mereka yang mengalami masalah ini dan ingin perbaikan yang sangat cepat (dan macet pada 9.4.5 atau sebelumnya), inilah yang saya lakukan:
Pembuatan tabel uji
Perbarui pernyataan untuk mengubah nama properti jsonb
Pada akhirnya, jawaban yang diterima adalah benar karena Anda tidak dapat memodifikasi satu bagian dari objek jsonb (dalam 9.4.5 atau sebelumnya); Namun, Anda bisa melemparkan objek jsonb ke string (:: TEXT) dan kemudian memanipulasi string dan melemparkan kembali ke objek jsonb (:: jsonb).
Ada dua peringatan penting
Dengan mengatakan itu, saya menemukan situasi di mana saya harus memperbarui skema untuk konten di objek jsonb dan ini adalah cara paling sederhana untuk mencapai apa yang diminta oleh poster asli.
sumber
\u0000
karakter nol, contoh menunjukkan gambar lengkap. Terima kasih untuk ini!replace(data::TEXT, '"name":', '"my-other-name":')::jsonb
Pertanyaan ini ditanyakan dalam konteks postgres 9.4, namun pemirsa baru yang datang ke pertanyaan ini harus menyadari bahwa di postgres 9.5, sub-dokumen Operasi / Perbarui / Hapus operasi pada bidang JSONB secara asli didukung oleh database, tanpa perlu ekstensi fungsi.
Lihat: JSONB memodifikasi operator dan fungsi
sumber
perbarui atribut 'nama':
dan jika Anda ingin menghapus, misalnya, atribut 'nama' dan 'tag':
sumber
Saya menulis fungsi kecil untuk diri saya sendiri yang bekerja secara rekursif di Postgres 9.4. Saya memiliki masalah yang sama (baik mereka memecahkan beberapa sakit kepala ini di Postgres 9.5). Pokoknya di sini adalah 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
jsonb_build_object
diperkenalkan pada 9,5Mungkin: UPDATE test SET data = '"my-other-name"' :: json WHERE id = 1;
Ini bekerja dengan kasus saya, di mana data adalah tipe json
sumber
Matheus de Oliveira membuat fungsi praktis untuk operasi JSON CRUD di postgresql. Mereka dapat diimpor menggunakan \ i directive. Perhatikan fungsi jsonb fork jika jsonb jika tipe data Anda.
9.3 json https://gist.github.com/matheusoliveira/9488951
9,4 jsonb https://gist.github.com/inindev/2219dff96851928c2282
sumber