Bagaimana cara kueri menggunakan bidang di dalam tipe data JSON PostgreSQL baru?

216

Saya mencari beberapa dokumen dan / atau contoh untuk fungsi JSON baru di PostgreSQL 9.2.

Secara khusus, diberikan serangkaian catatan JSON:

[
  {name: "Toby", occupation: "Software Engineer"},
  {name: "Zaphod", occupation: "Galactic President"}
]

Bagaimana saya menulis SQL untuk menemukan catatan dengan nama?

Dalam vanilla SQL:

SELECT * from json_data WHERE "name" = "Toby"

Manual dev resmi sangat jarang:

Perbarui I

Saya telah mengumpulkan inti yang merinci apa yang mungkin saat ini dengan PostgreSQL 9.2 . Menggunakan beberapa fungsi khusus, dimungkinkan untuk melakukan hal-hal seperti:

SELECT id, json_string(data,'name') FROM things
WHERE json_string(data,'name') LIKE 'G%';

Pembaruan II

Saya sekarang telah memindahkan fungsi JSON saya ke proyek mereka sendiri:

PostSQL - satu set fungsi untuk mengubah PostgreSQL dan PL / v8 menjadi toko dokumen JSON yang benar-benar hebat

Toby Hede
sumber
3
Baru-baru ini saya menemukan posting blog ini oleh Matt Schinckel, yang menjelaskan secara rinci kueri JSON di PostgreSQL schinckel.net/2014/05/25/querying-json-in-postgres
knowbody
1
@ knowbody Posting ini sebenarnya tentang permintaan JSONB, yang sangat berbeda dari JSON. Buruk saya karena tidak membuat lebih jelas dalam posting.
Matthew Schinckel

Jawaban:

177

Postgres 9.2

Saya mengutip Andrew Dunstan pada daftar pgsql-hacker :

Pada tahap tertentu mungkin akan ada beberapa fungsi pemrosesan json (sebagai lawan dari produksi json), tetapi tidak di 9.2.

Tidak mencegahnya dari memberikan contoh implementasi di PLV8 yang seharusnya menyelesaikan masalah Anda.

Postgres 9.3

Menawarkan gudang fungsi dan operator baru untuk menambahkan "pemrosesan json".

Jawaban untuk pertanyaan asli di Postgres 9.3:

SELECT *
FROM   json_array_elements(
  '[{"name": "Toby", "occupation": "Software Engineer"},
    {"name": "Zaphod", "occupation": "Galactic President"} ]'
  ) AS elem
WHERE elem->>'name' = 'Toby';

Contoh lanjutan:

Untuk tabel yang lebih besar, Anda mungkin ingin menambahkan indeks ekspresi untuk meningkatkan kinerja:

Postgres 9.4

Tambah jsonb(b untuk "biner", nilai disimpan sebagai tipe Postgres asli) dan lebih banyak fungsi untuk kedua jenis. Selain indeks ekspresi yang disebutkan di atas, jsonbjuga mendukung GIN, btree dan indeks hash , GIN menjadi yang paling kuat dari semua ini.

Manual ini sejauh menyarankan:

Secara umum, sebagian besar aplikasi harus memilih untuk menyimpan data JSON sebagai jsonb , kecuali ada kebutuhan yang cukup khusus, seperti asumsi warisan tentang pemesanan kunci objek.

Penekanan berani saya.

Manfaat kinerja dari perbaikan umum hingga indeks GIN.

Postgres 9.5

Lengkap jsonbfungsi dan operator. Tambahkan lebih banyak fungsi untuk dimanipulasijsonb di tempat dan untuk tampilan.

Erwin Brandstetter
sumber
1
Terima kasih, saya mengalami masalah jenis dengan sangat cepat menggunakan pendekatan PLV8. Terlihat menjanjikan, tetapi tidak bisa digunakan saat ini.
Toby Hede
@TobyHede: Kira kita harus menunggu 9,3 kalau begitu.
Erwin Brandstetter
1
@ JooeShaw: Terima kasih, saya memperbarui dan menambahkan tautan ke Wiki Postgres.
Erwin Brandstetter
@ErwinBrandstetter jika saya mencari WHERE elem - >> 'correct' = 'TRUE'; dan JSON terlihat seperti ini: "benar": "BENAR", apa cara yang tepat untuk menanyakan istilah yang logis?
Shiraj
@Shiraj: Silakan tanyakan pertanyaan baru sebagai pertanyaan . Komentar bukan tempatnya.
Erwin Brandstetter
87

Dengan Postgres 9.3+, cukup gunakan ->operator. Sebagai contoh,

SELECT data->'images'->'thumbnail'->'url' AS thumb FROM instagram;

lihat http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/ untuk beberapa contoh bagus dan tutorial.

Meekohi
sumber
2
Dalam contoh di atas Anda harus memiliki lapangan yang bernama datadengan dokumen JSON: {images:{thumbnail:{url:'thumbnail.jpg'}}}. Beri tahu kami seperti apa data Anda dan permintaan apa yang gagal.
Meekohi
6
Bagaimana Anda bisa bertanya jika ada array? Saya melihat operator # >> tetapi tidak tahu bagaimana menggunakannya!
Mohamed El Mahallawy
Dalam kueri pemilihan ini, bisakah saya menggunakan wildcard? YaituSELECT data->'%'->'thumbnail'->'url' AS thumb FROM instagram;
Bharat
Jawaban @ Meekohi bekerja dengan baik: khususnya saya tidak perlu ::jsonseperti yang dijelaskan dalam posting lain. Juga perhatikan ->operator akan membuat kesalahan jika Anda mencoba mengakses properti yang tidak ada (yaitu jika Anda memiliki JSON terhuyung-huyung):ERROR: column "jsonPropertyYouWant" does not exist
The Red Pea
19

Dengan postgres 9.3 gunakan -> untuk akses objek. 4 contoh

seed.rb

se = SmartElement.new
se.data = 
{
    params:
    [
        {
            type: 1,
            code: 1,
            value: 2012,
            description: 'year of producction'
        },
        {
            type: 1,
            code: 2,
            value: 30,
            description: 'length'
        }
    ]
}

se.save

rel c

SELECT data->'params'->0 as data FROM smart_elements;

kembali

                                 data
----------------------------------------------------------------------
 {"type":1,"code":1,"value":2012,"description":"year of producction"}
(1 row)

Anda dapat terus bersarang

SELECT data->'params'->0->'type' as data FROM smart_elements;

kembali

 data
------
 1
(1 row)
joseAndresGomezTovar
sumber