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

Facebook
Twitter
LinkedIn
Google+
http://kurzyniec.pl/artykuly/full-text-search-query/

Leave a Reply

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