PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Indeks untuk menemukan elemen dalam array JSON

jsonb di Postgres 9.4+

Tipe data JSON biner jsonb sebagian besar meningkatkan opsi indeks. Anda sekarang dapat memiliki indeks GIN di jsonb array secara langsung:

CREATE TABLE tracks (id serial, artists jsonb);  -- !
CREATE INDEX tracks_artists_gin_idx ON tracks USING gin (artists);

Tidak perlu fungsi untuk mengonversi array. Ini akan mendukung kueri:

SELECT * FROM tracks WHERE artists @> '[{"name": "The Dirty Heads"}]';

@> menjadi jsonb operator "berisi", yang dapat menggunakan indeks GIN. (Bukan untuk json , hanya jsonb !)

Atau Anda menggunakan kelas operator GIN non-default yang lebih khusus jsonb_path_ops untuk indeks:

CREATE INDEX tracks_artists_gin_idx ON tracks
USING  gin (artists jsonb_path_ops);  -- !

Kueri yang sama.

Saat ini jsonb_path_ops hanya mendukung @> operator. Tapi biasanya jauh lebih kecil dan lebih cepat. Ada lebih banyak opsi indeks, detail dalam manual .

Jika kolom artists hanya menyimpan nama seperti yang ditampilkan dalam contoh, akan lebih efisien jika hanya menyimpan nilai sebagai teks JSON primitif dan kunci red yang berlebihan bisa menjadi nama kolom.

Perhatikan perbedaan antara objek JSON dan tipe primitif:

  • Menggunakan indeks dalam array json di PostgreSQL
CREATE TABLE tracks (id serial, artistnames jsonb);
INSERT INTO tracks  VALUES (2, '["The Dirty Heads", "Louis Richards"]');

CREATE INDEX tracks_artistnames_gin_idx ON tracks USING gin (artistnames);

Pertanyaan:

SELECT * FROM tracks WHERE artistnames ? 'The Dirty Heads';

? tidak bekerja untuk objek nilai , cukup kunci dan elemen larik .

Atau:

CREATE INDEX tracks_artistnames_gin_idx ON tracks
USING  gin (artistnames jsonb_path_ops);

Pertanyaan:

SELECT * FROM tracks WHERE artistnames @> '"The Dirty Heads"'::jsonb;

Lebih efisien jika nama sangat duplikasi.

json di Postgres 9.3+

Ini harus bekerja dengan IMMUTABLE fungsi :

CREATE OR REPLACE FUNCTION json2arr(_j json, _key text)
  RETURNS text[] LANGUAGE sql IMMUTABLE AS
'SELECT ARRAY(SELECT elem->>_key FROM json_array_elements(_j) elem)';

Buat indeks fungsional ini :

CREATE INDEX tracks_artists_gin_idx ON tracks
USING  gin (json2arr(artists, 'name'));

Dan gunakan kueri seperti ini. Ekspresi dalam WHERE klausa harus cocok dengan yang ada di indeks:

SELECT * FROM tracks
WHERE  '{"The Dirty Heads"}'::text[] <@ (json2arr(artists, 'name'));

Diperbarui dengan umpan balik dalam komentar. Kita perlu menggunakan operator array untuk mendukung indeks GIN.
Operator "diisi oleh" <@ dalam hal ini.

Catatan tentang volatilitas fungsi

Anda dapat mendeklarasikan fungsi Anda IMMUTABLE bahkan jika json_array_elements() bukan tidak.
Sebagian besar JSON fungsi yang dulunya hanya STABLE , bukan IMMUTABLE . Ada diskusi di daftar peretas untuk mengubahnya. Sebagian besar IMMUTABLE sekarang. Periksa dengan:

SELECT p.proname, p.provolatile
FROM   pg_proc p
JOIN   pg_namespace n ON n.oid = p.pronamespace
WHERE  n.nspname = 'pg_catalog'
AND    p.proname ~~* '%json%';

Indeks fungsional hanya berfungsi dengan IMMUTABLE fungsi.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Pisahkan kolom menjadi beberapa baris di Postgres

  2. Pilih Postgresql hingga jumlah total tertentu tercapai

  3. Bagaimana cara membuat pencarian fuzzy sederhana hanya dengan PostgreSQL?

  4. Bagaimana cara mengkonfigurasi HikariCP untuk postgresql?

  5. Bagaimana cara membuat ekstensi postgres di dalam wadah?