Mam tabelę bazy danych PostgreSQL z wierszami zawierającymi kilka zdań / akapitów tekstu.

Powiedzmy, że istnieją trzy rekordy (bezsensowne, na przykład):

1) A dancing fox ran across the road.
2) I like dancing foxtrot.
3) These animals are foxes.

Chciałbym wyszukać „tańczący lis” i spodziewam się, że powinien zwrócić tylko „rekord 1”.

Jednak gdy użyję wieloznacznej składni %dancing fox% LIKE, odzyskam rekordy 1 i 2.

Spodziewałem się, że tsvector może być rozwiązaniem, ale projekt wykorzystuje więcej lokalizacji (problem 1) i nie chcę, aby pasował do trzeciego rekordu - nie chcę prawdziwego pełnego tekstu (problem 2).

Co sugerowałbyś użyć? A może masz jakieś doświadczenia lub linki do źródeł, jak radzić sobie z problemami 1 i 2?

Wiem, że moje pytanie jest dość zagmatwane, więc dziękuję za cierpliwość. Może po prostu muszę zostać popchnięty we właściwym kierunku.

1
JCZ 2 kwiecień 2020, 19:51

3 odpowiedzi

Najlepsza odpowiedź

Możesz używać wyszukiwania pełnotekstowego z „prostą” konfiguracją, aby uniknąć specyficznych dla języka słów kluczowych i pomijanych, oraz operatorów dopasowania do wyrażenia, aby zachować kolejność wyrazów i odstępy.

select * from foo 
    where to_tsvector('simple',x)  @@ phraseto_tsquery('simple','dancing fox');

Mówisz, że nie chcesz dopasować trzeciego przykładu, ale nie jest jasne, dlaczego miałby to zrobić w pierwszej kolejności, nawet jeśli używałeś „angielski” i plainto_tsquery zamiast „prosty” i {{X1 }}.

Nadal jesteś na łasce tego, co domyślny parser tekstu FTS uważa za słowo, ale żaden z twoich przykładów nie dotyka tego punktu (co by było, gdyby fox-trot był łączony?)

Będzie to obsługiwane przez zwykłe indeksy FTS na typach tsvector.

Lub, jak sugeruje Google Moja Firma, możesz użyć ~ i „\ y”. Ten typ zapytania będzie obsługiwany przez indeksy pg_trgm. Myślę, że to rozwiązanie jest bardziej intuicyjne, ale jeśli teksty są długie, może być mniej wydajne.

1
jjanes 3 kwiecień 2020, 17:34

Możesz dodać separatory:

where concat(' ', col, ' ') like '% dancing fox %'
2
Gordon Linoff 2 kwiecień 2020, 16:52

Możesz to zrobić za pomocą wyrażenia regularnego.

Granice słów \y przydają się: mogą istnieć inne znaki niż spacja, które ograniczają słowa.

where mycol ~ '\ydancing fox\y'

Jak wyjaśniono w dokumentacji: \y odpowiada tylko na początku lub na końcu słowa .

3
GMB 2 kwiecień 2020, 16:54