FREETEXT: примеры (SQL)
FREETEXT(column_name | column_list | '*', freetext_string [, LANGUAGE language_term]): intОписание функции FREETEXT
Функция FREETEXT применяется для полнотекстового поиска в SQL Server. Она анализирует текст на естественном языке, разбивая его на отдельные слова, и выполняет поиск совпадений, учитывая синонимы и различные словоформы.
Использование функции актуально в ситуациях, когда требуется не точное совпадение, а поиск по смыслу. Например, в поисковых системах интернет-магазинов или баз знаний, где пользователи формулируют запросы в свободной форме.
Аргументы функции
- column – имя столбца с типом данных, для которого настроен полнотекстовый индекс. Можно указать несколько столбцов.
- freetext_string – текст для поиска. Функция разбивает эту строку на отдельные слова, исключая стоп-слова, и ищет их синонимы в соответствии с тезаурусом.
- language – необязательный параметр, указывающий идентификатор языка. Если он не задан, используется язык, установленный для столбца в полнотекстовом индексе.
Возвращаемое значение
Функция возвращает табличное значение с одним столбцом [KEY], который содержит уникальные идентификаторы строк (ключи полнотекстового индекса), соответствующие условию поиска. Эти данные используются в предложении FROM совместно с оператором JOIN.
Примеры базового использования
Простой запрос для поиска по одному столбцу:
SELECT * FROM Products
WHERE FREETEXT(Description, 'comfortable office chair');Использование в JOIN с указанием языка:
SELECT p.*
FROM Products p
INNER JOIN FREETEXTTABLE(Products, Description, 'ergonomic keyboard', LANGUAGE 'English') AS ft
ON p.ProductID = ft.[KEY];Результат для обоих запросов — набор строк, где в описании товара встречаются слова, связанные по смыслу с запросом «удобное офисное кресло» или «эргономичная клавиатура».
Похожие функции в MS SQL
В MS SQL Server существует несколько функций для полнотекстового поиска, каждая со своей спецификой.
- CONTAINS — функция для точного поиска слов или фраз с использованием предикатов и операторов. Она более точная, но менее гибкая в сравнении с FREETEXT, так как не учитывает морфологию и синонимы автоматически.
- FREETEXTTABLE
FREETEXT предпочтительнее, когда требуется нечеткий поиск по смыслу, а CONTAINS — для точного соответствия конкретным терминам или комбинациям слов.
Альтернативы в других СУБД
В других базах данных существуют аналогичные механизмы.
PostgreSQL
Используются функции to_tsvector и to_tsquery с оператором @@.
SELECT * FROM articles
WHERE to_tsvector('english', body) @@ to_tsquery('english', 'comfortable & chair');MySQL
Применяется MATCH ... AGAINST в режиме естественного языка.
SELECT * FROM products
WHERE MATCH(description) AGAINST('office chair' IN NATURAL LANGUAGE MODE);Oracle и SQLite используют свои расширения для полнотекстового поиска, но они не являются стандартными и требуют дополнительной настройки. Главное отличие — в синтаксисе и степени интеграции с ядром СУБД.
Типичные ошибки
Частая проблема — отсутствие полнотекстового индекса на целевом столбце.
SELECT * FROM Documents WHERE FREETEXT(Content, 'report');
-- Ошибка: Cannot use a CONTAINS or FREETEXT predicate on table 'Documents'
-- because it is not full-text indexed.Ошибка может возникать при использовании функции в неподдерживаемом контексте, например, в CHECK-ограничении.
Еще одна проблема — неправильное указание столбца или языка, что приводит к отсутствию результатов или ошибкам выполнения запроса.
Изменения в последних версиях
В SQL Server 2012 появилась поддержка семантического поиска, который может использоваться совместно с FREETEXT для определения ключевых фраз и схожести документов. В более новых версиях улучшена производительность и расширены языковые пакеты для тезауруса.
SQL Server 2017 и выше включает обновления в обработке стоп-слов и улучшения в ранжировании результатов для функции FREETEXTTABLE.
Расширенные примеры
Поиск по нескольким столбцам с указанием языка:
SELECT * FROM Books
WHERE FREETEXT((Title, Summary), 'detective story', LANGUAGE 'Russian');Использование FREETEXTTABLE с сортировкой по релевантности:
SELECT b.Title, ft.[RANK]
FROM Books b
INNER JOIN FREETEXTTABLE(Books, (Title, Summary), 'historical novel') AS ft
ON b.BookID = ft.[KEY]
ORDER BY ft.[RANK] DESC;Поиск с объединением условий:
SELECT * FROM News
WHERE FREETEXT(Article, 'economic growth')
AND PublicationDate > '2023-01-01';Вложенный запрос для фильтрации:
SELECT * FROM
(SELECT *, FREETEXT(Comments, 'excellent product') AS IsRelevant FROM Reviews) AS SubQuery
WHERE IsRelevant = 1;