Uzyskaj częściowe dopasowanie z kolumny TSVECTOR indeksowanej GIN

13

Chciałbym uzyskać wyniki przez zapytanie to:

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

To działa i zwraca wiersze tsvzawierające Available. Ale jeśli użyję avai(upuszczę lable), nic nie znajdzie.

Czy wszystkie zapytania muszą być w słowniku? Czy nie możemy po prostu zapytać o takie litery? Mam bazę danych zawierającą treść (treść) wiadomości e-mail i chciałbym, aby była szybka, ponieważ rośnie z każdą sekundą. Obecnie używam

... WHERE content ~* 'letters`
Xangr
źródło

Odpowiedzi:

22

Czy wszystkie zapytania muszą być w słowniku?

Nie. Ponieważ na początku w indeksie znajdują się tylko słowa kluczowe (zgodnie z używaną konfiguracją wyszukiwania tekstowego ). Ale co ważniejsze:

Nie . Ponieważ, na szczycie tej Full Text Search jest również zdolny do dopasowywania przedrostka :

To by działało:

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

Uwaga 3 rzeczy:

  1. Użyj to_tsquery()nie plainto_tsquery(), w tym przypadku, ponieważ ( cytując instrukcję ):

    ... plainto_tsquerynie rozpoznaje tsqueryoperatorów, etykiet wagowych ani etykiet z dopasowaniem prefiksu w danych wejściowych

  2. Użyj 'simple'konfiguracji wyszukiwania tekstu, aby wygenerować, tsqueryponieważ oczywiście chcesz wziąć słowo „skorzystaj”, jak jest, a nie stosować.

  3. Dołącz, :*aby uczynić to wyszukiwanie prefiksem, tzn. Znajdź wszystkie leksemy zaczynające się na „avail”.

Ważne: Jest to wyszukiwanie prefiksu leksemów (rdzeni słów) w dokumencie. Wyrażenie regularne bez symboli wieloznacznych ( content ~* 'avail') nie jest dokładnie takie samo! Ten ostatni nie jest zakotwiczony w lewo (do początku leksemów) i znalazłby również „FOOavail” itp.

Nie jest jasne, czy chcesz, aby zachowanie zostało przedstawione w zapytaniu, czy też odpowiednik dodanego wyrażenia regularnego. Sugerowane już indeksy Trigram ( pg_trgm) jak @Evan są do tego odpowiednim narzędziem. Na dba.SE znajduje się wiele powiązanych pytań, spróbuj wyszukać .

Przegląd:

Próbny

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

Ostatnia pokrewna odpowiedź (rozdział Różne podejście do optymalizacji wyszukiwania ):

E-maile

Ponieważ wspomniałeś o wiadomościach e-mail, pamiętaj, że parser wyszukiwania tekstu identyfikuje wiadomości e-mail i nie dzieli ich na osobne słowa / leksemy. Rozważać:

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

Zastąpiłbym separatory @i .wiadomości e-mail spacją ( ' '), aby indeksować zawarte słowa.

Ponadto, ponieważ masz do czynienia z nazwiskami w wiadomościach e-mail, a nie ze słowami angielskimi (lub innymi językami) , 'simple'użyłbym konfiguracji wyszukiwania tekstowego, aby wyłączyć funkcję wyszukiwania i inne funkcje językowe :

Zbuduj ts_vectorkolumnę za pomocą:

SELECT to_tsvector('simple', translate('[email protected]', '@.', '  ')) AS tsv;
Erwin Brandstetter
źródło
Usuwam swoją odpowiedź na to pytanie, ponieważ tak czy inaczej, ponieważ wyraźnie się mylę po raz pierwszy i wolałbym, żeby mi o tym nie przypominano. Mam dla ciebie dwa pytania: 1) gdzie jest :*udokumentowane, i 2) czy wzmianka o budowaniu nie powinna to_tsvector('simple'..)iść w parze z instrukcjami, że przyszłe zapytania tego tsv będą wymagały również „prostej” konfiguracji do tsquery? Myślę, że powinieneś wyjaśnić konsekwencje wyłączenia w tsvector / tsquery.
Evan Carroll
@EvanCarroll: Korzystanie z „prostej” konfiguracji nie jest wymagane . Po prostu unika się tego (jak „szczury” do „szczura”), co może, ale nie musi być pożądane. Niepożądane dla podanego przykładu. Podręcznik: Dodałem linki powyżej ...
Erwin Brandstetter,
4
@EvanCarroll: Poza tym: Myślenie, że się mylisz za pierwszym razem, byłoby drugim razem. I to byłoby złe, rekurencyjnie. ;)
Erwin Brandstetter,
2
@ErwinBrandstetter, Wow, po prostu dałeś mi pełną prędkość wyszukiwania. Przed tobą to działa, 0.380msaby uzyskać wynik. Po twojej drodze to zajęło 0.079 ms.
xangr
1
@xangr: Nie, FTS oferuje dopasowanie tylko prefiksów dla leksemów. Więcej informacji znajdziesz w pg_trgm. FTS jest szybszy (z mniejszym indeksem). Możesz nawet połączyć oba indeksy ...
Erwin Brandstetter