Dapatkan kecocokan sebagian dari kolom TSVECTOR yang diindeks GIN


13

Saya ingin mendapatkan hasil dengan permintaan ini:

SELECT * FROM (
  SELECT id, subject
  FROM mailboxes
  WHERE tsv @@ plainto_tsquery('avail')
) AS t1 ORDER by id DESC;

Ini berfungsi dan mengembalikan baris dengan yang tsvmengandung Available. Tetapi jika saya menggunakan avai(menjatuhkan lable) itu tidak dapat menemukan apa pun.

Apakah semua pertanyaan harus ada dalam kamus? Tidak bisakah kita meminta surat seperti itu? Saya memiliki basis data yang berisi isi email dan saya ingin membuatnya secepat pertumbuhannya setiap detik. Saat ini saya menggunakan

... WHERE content ~* 'letters`

Jawaban:


22

Apakah semua pertanyaan harus ada dalam kamus?

Tidak. Karena hanya kata batang (sesuai dengan konfigurasi pencarian teks yang digunakan ) yang ada dalam indeks untuk memulai. Tetapi yang lebih penting:

Tidak ada . Karena, di atas itu Pencarian Teks Lengkap juga mampu mencocokkan awalan :

Ini akan berhasil:

SELECT id, subject
FROM   mailboxes
WHERE  tsv @@ to_tsquery('simple', 'avail:*')
ORDER  BY id DESC;

Perhatikan 3 hal:

  1. Gunakan to_tsquery(), bukan plainto_tsquery(), dalam hal ini karena ( mengutip manual ):

    ... plainto_tsquerytidak akan mengenali tsqueryoperator, label bobot, atau label kecocokan awalan dalam inputnya

  2. Gunakan 'simple'konfigurasi pencarian teks untuk menghasilkan tsquerykarena Anda jelas ingin mengambil kata 'faedah' apa adanya dan tidak berlaku stemming.

  3. Tambahkan :*untuk menjadikannya pencarian awalan, yaitu menemukan semua leksem dimulai dengan 'tersedia'.

Penting: Ini adalah pencarian awalan pada leksem (batang kata) dalam dokumen. Pencocokan ekspresi reguler tanpa wildcard ( content ~* 'avail') tidak persis sama! Yang terakhir ini tidak berlabuh kiri (ke awal leksem) dan juga akan menemukan 'FOOavail' dll.

Tidak jelas apakah Anda ingin perilaku yang diuraikan dalam kueri Anda atau yang setara dengan ekspresi reguler yang ditambahkan. Indeks trigram ( pg_trgm) seperti @Evan sudah disarankan adalah alat yang tepat untuk itu. Ada banyak pertanyaan terkait di dba.SE, coba cari .

Gambaran:

Demo

SELECT *
FROM (
   VALUES
     ('Zend has no framework')
   , ('Zend Framework')
   ) sub(t), to_tsvector(t) AS tsv
WHERE tsv @@ to_tsquery('zend <-> fram:*');
 id |       t        |          tsv
----+----------------+------------------------
  2 | Zend Framework | 'framework':2 'zend':1

Jawaban terkait baru-baru ini (bab Pendekatan berbeda untuk mengoptimalkan pencarian ):

Email?

Karena Anda menyebutkan email, ketahuilah bahwa parser pencarian teks mengidentifikasi email dan tidak membaginya menjadi kata / leksem yang terpisah. Mempertimbangkan:

SELECT ts_debug('english', 'xangr@some.domain.com')
(email,"Email address",xangr@some.domain.com,{simple},simple,{xangr@some.domain.com})

Saya akan mengganti pemisah @dan .dalam email Anda dengan space ( ' ') untuk mengindeks kata-kata yang terkandung.

Juga, karena Anda berurusan dengan nama dalam email, bukan dengan kata-kata bahasa Inggris (atau bahasa lain) , saya akan menggunakan 'simple'konfigurasi pencarian teks untuk menonaktifkan fitur stemming dan bahasa lainnya :

Bangun ts_vectorkolom dengan:

SELECT to_tsvector('simple', translate('joe.xangr@some.domain.com', '@.', '  ')) AS tsv;

Saya menghapus jawaban saya untuk ini karena bagaimanapun juga karena saya jelas salah untuk pertama kalinya dan saya lebih suka tidak diingatkan akan hal itu. Saya punya dua pertanyaan untuk Anda 1) di mana :*didokumentasikan, dan 2) tidak boleh menyebutkan untuk membangun to_tsvector('simple'..)datang bersama-sama dengan instruksi bahwa permintaan masa depan tsv itu akan memerlukan konfigurasi 'sederhana' juga untuk pembuatan? Saya pikir Anda harus mengklarifikasi konsekuensi penonaktifan yang berasal dari tsvector / tsquery.
Evan Carroll

@EvanCarroll: Tidak diperlukan konfigurasi 'sederhana' . Itu hanya menghindari stemming (seperti 'tikus' ke 'tikus') yang mungkin atau mungkin tidak diinginkan. Tidak diinginkan untuk contoh yang diberikan. Manual: Saya telah menambahkan tautan di atas ...
Erwin Brandstetter

4
@EvanCarroll: Di samping: Mengira Anda salah saat pertama kali, akan menjadi yang kedua kalinya. Dan itu akan salah, secara rekursif. ;)
Erwin Brandstetter

2
@ ErwinBrandstetter, Wow, caramu baru saja memberi saya pencarian kecepatan penuh. Sebelum cara Anda dibutuhkan 0.380msuntuk mendapatkan hasil. Setelah cara Anda mengambil 0.079 ms.
xangr

1
@xangr: Tidak, FTS hanya menawarkan pencocokan awalan untuk leksem. Untuk yang lainnya, lihat pg_trgm. FTS lebih cepat (dengan indeks yang lebih kecil). Anda bahkan dapat menggabungkan kedua indeks ...
Erwin Brandstetter
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.