Full-Text Search – zadawanie zapytań

W poprzednim artykule została opisana instalacja i konfiguracja wyszukiwania pełnotekstowego dla języka polskiego. Do całości rozwiązania brakowało jednak sposobu zadawania zapytań na indeks FTS, co opisałem w tym artykule.

Zadawać zapytania można tylko na kolumnach o typie tekstowym (char, varchar, nchar, nvarchar, text, ntext, image, xml, varbinary). Można to zrealizować na dwa sposoby. Pierwszy z nich wykorzystuje predykaty CONTAINS oraz FREETEXT. Druga metoda wykorzystuje funkcje CONTAINSTABLE oraz FREETEXTTABLE.

Predykaty

FREETEXT
Podczas użycia predykatu FREETEXT silnik FTS wykonuje następujące akcje:
– separuje wyrazy (word-breaking),
– generuje fleksyjne formy wyrazów (stemming),
– identyfikuje wyrazy ze słownikiem wyrazów blizkoznacznych,
– przypisuje wagi wyrażeniom.
Po wykonaniu powyższych kroków silnik FTS szuka dopasowań.

Do jego cech należy zaliczyć:
– poszukuje słów wyrazów wyekstrahowanych z podanego tekstu zapytania,
– nie wszystkie słowa muszą zostać znalezione,
– uwzględnia odmiany wyrazów i synonimy,
– mniej precyzyjny niż predykat CONTAINS.

SELECT *
FROM Documents
WHERE FREETEXT (DocumentContent, 'jedyny motocyklista')

CONTAINS
Predykat cechuje się bardzo rozbudowaną składnią, która wykorzystuje słowa kluczowe oraz znaki specjalne. Daje to możliwość zbudowania zaawansowanego zapytania z dokładnym określeniem oczekiwanego wyniku. Podczas korzystania z CONTAINS należy sprecyzować przynajmniej jeden warunek przeszukiwania w przeciwnym razie otrzymamy błąd.

Używając CONTAINS można wyszukać:
– słowa lub frazy (‘word’),
– słowa lub frazy rozpoczynające się tekstem (“word*”),
– słowa położonego blisko innych wyrazów (‘fox NEAR chicken’),
– fleksyjne formy wyrazów (‘FORMSOF (INFLECTIONAL, ride)’),
– synonimy wyrazów (‘FORMSOF (THESAURUS, metal)’).

SELECT *
FROM Documents
WHERE CONTAINS (DocumentContent, 'jedyny OR "moto*"')
SELECT *
FROM Documents
WHERE CONTAINS (DocumentContent, 'FORMSOF(INFLECTIONAL, "motocykl")')
SELECT *
FROM Documents
WHERE CONTAINS(DocumentContent, 'ISABOUT (kierowca WEIGHT (.4), motocyklista WEIGHT (.8) )')

Funkcje

Funkcje CONTAINSTABLE oraz FREETEXTTABLE zwracają tabelę z wynikami dopasowanych wierszy. Tabela zawiera dwie kolumny. Pierwsza z nich to kolumna KEY, w kórej znajdują się wartości klucza unikalnego z indeksu FTS. Druga – RANK – zawiera wartość dopasowania, czyli w jakim stopniu wiersz pasuje do zadanych kryteriów wyszukiwania. Daje to możliwość oceny stopnia podobieństwa zadanych wyrazów z tekstem każdego wiersza FTS.
CONTAINSTABLE oraz FREETEXTTABLE posiadają identyczne cechy oraz sposób działania jak odpowiadające im predykaty.

SELECT Id, FREETEXTTABLE_ALIAS.RANK, DocumentContent
FROM Documents d INNER JOIN FREETEXTTABLE (Documents, DocumentContent, 'jedyny motocyklista') 
	AS FREETEXTTABLE_ALIAS ON d.Id = FREETEXTTABLE_ALIAS.[KEY]
ORDER BY 2 DESC
SELECT Id, CONTAINSTABLE_ALIAS.RANK, DocumentContent
FROM Documents d INNER JOIN CONTAINSTABLE (Documents, DocumentContent, 'jedyny OR "moto*"', 3) 
	AS CONTAINSTABLE_ALIAS ON d.Id = CONTAINSTABLE_ALIAS.[KEY]
SELECT Id, CONTAINSTABLE_ALIAS.RANK, DocumentContent
FROM Documents d INNER JOIN CONTAINSTABLE (Documents, DocumentContent, 'FORMSOF(INFLECTIONAL, "motocykl")') 
	AS CONTAINSTABLE_ALIAS ON d.Id = CONTAINSTABLE_ALIAS.[KEY]

Zapytanie FTS

FREETEXT vs CONTAINS vs LIKE

W zależności od oczekiwanego wyniku, predykatów należy stosować do różnego rodzaju przeszukiwania:

  • FREETEXT należy stosować do dopasowania znaczenia słów, a nie dokładnej treści. Wyniki są generowane jeśli przynajmniej jedno słowo zostanie znalezione.
  • CONTAINS należy użyć do precyzyjnego wyszukiwania pojedyńczych wyrazów, ich wyrazów bliskoznacznych (z określeniem pewnego dystansu) oraz określenia wagi zgodności.
  • predykatem LIKE można szukać tylko zadaną frazą bez uwzględnienia różnych form wyrazów. Dodatkowo wykonanie zapytania LIKE na dużej ilości danych teksowych jest znacznie wolniejsze od zapytań FTS.

Podbij

Leave a Reply

Your email address will not be published. Required fields are marked *