GIN endeksli TSVECTOR sütunundan kısmi eşleşmeyi alın


13

Bu sorgu ile sonuç almak istiyorum:

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

Bu tsviçeren ve satır içeren içeren çalışır Available. Ama kullanırsam avai(düşürürsem lable) hiçbir şey bulamaz.

Tüm sorguların sözlükte olması gerekiyor mu? Sadece bu harfleri sorgulayamaz mıyız? E-posta gövdesi (içerik) içeren bir veritabanım var ve her saniye büyüdükçe hızlı hale getirmek istiyorum. Şu anda kullanıyorum

... WHERE content ~* 'letters`

Yanıtlar:


22

Tüm sorguların sözlükte olması gerekiyor mu?

Hayır. Çünkü başlangıçta sadece kelime sapları (kullanılan metin arama yapılandırmasına göre ) dizinde bulunur. Ama daha önemlisi:

Hayır . Bunun üzerine, Çünkü ara Tam Metin de yapabilen önek eşleşmesi :

Bu işe yarar:

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

Not 3 şeyler:

  1. Kullanım to_tsquery()değil plainto_tsquery(), bu durumda (çünkü kılavuzu alıntı ):

    ... girişindeki operatörleri, ağırlık etiketlerini veya ön ek eşleme etiketlerini plainto_tsquerytanımayacaktsquery

  2. Açıkçası 'avail' kelimesini olduğu gibi almak ve stemming'i uygulamak istemediğiniz 'simple'için üretmek için metin arama yapılandırmasını kullanın .tsquery

  3. :*Bir önek araması yapmak için ekleyin , yani 'boşuna' ile başlayan tüm sözcükleri bulun.

Önemli: Bu, belgedeki sözcükler (sözcük sapları) üzerinde bir önek aramasıdır. Joker karakter ( content ~* 'avail') içermeyen normal ifade eşleşmesi tam olarak aynı değildir! İkincisi sola sabitlenmez (lexemlerin başlangıcına kadar) ve ayrıca 'FOOavail' vb.

Sorgunuzda belirtilen davranışın veya eklenen normal ifadenin eşdeğerinin belirtilmesini isteyip istemediğiniz açık değildir. @Evanpg_trgm gibi önerilen trigram indeksleri ( ) bunun için doğru araçtır. Dba.SE ile ilgili birçok soru var, bir arama yapmayı deneyin .

Genel bakış:

gösteri

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

En son ilgili cevap ( Aramayı optimize etmek için farklı yaklaşım bölümü ):

E-postalar?

E-postalardan bahsettiğinizden, metin arama ayrıştırıcısının e-postaları tanımladığını ve bunları ayrı kelimelere / sözcüklere bölmediğini unutmayın. Düşünmek:

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

Ayırıcıları @ve .e-postalarınızda ' 'bulunan kelimeleri dizine eklemek için boşluk ( ) ile değiştiririm.

Ayrıca, İngilizce (veya başka bir dil) sözcüklerle değil, e-postalardaki adlarla uğraştığınızdan, stemming ve diğer dil özelliklerini devre dışı bırakmak için metin arama yapılandırmasını kullanacağım :'simple'

İnşa ts_vectorsütunu ile:

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

Bunun için cevabımı siliyorum çünkü her iki durumda da ilk kez açıkça yanılıyorum ve hatırlatmamayı tercih ederim. Sizin için iki sorum var 1) nerede :*belgelenmiştir ve 2) bu to_tsvector('simple'..)tsv'nin gelecekteki sorgulamasının tsquery için de 'basit' konfigürasyon gerektireceğini gösteren talimatlarla birlikte gelmek için söz etmemeliyiz? Bence bir tsvector / tsquery'de ortaya çıkan devre dışı bırakmanın sonuçlarını açıklığa kavuşturmalısınız.
Evan Carroll

@EvanCarroll: 'Basit' yapılandırmayı kullanmak gerekli değildir . Bu sadece istenebilecek olan veya olmayan köklenmeyi ('sıçanlardan' sıçana 'gibi) önler. Verilen örnek için arzu edilmez. Manuel: Yukarıdaki bağlantıları ekledim ...
Erwin Brandstetter

4
@EvanCarroll: Kenara: İlk kez yanlış olduğunu düşünmek , ikinci kez olur. Ve bu tekrar tekrar yanlış olur. ;)
Erwin Brandstetter 13:16

2
@ErwinBrandstetter, Wow, yolun bana tam hızlı bir arama yaptı. Yoldan önce 0.380mssonuç almak için tooks . Yolundan sonra sürdü 0.079 ms.
xangr

1
@xangr: Hayır, FTS yalnızca sözlükler için önek eşleşmesi sunar . Daha fazlası için bakın pg_trgm. FTS daha hızlıdır (daha küçük bir indeksle). Her iki dizini de birleştirebilirsiniz ...
Erwin Brandstetter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.