В данной статье рассматривается Часть 29286 г. обь – условный фрагмент технической документации, посвящённый работе с полнотекстовым поиском в СУБД PostgreSQL. Основное внимание уделяется функции to_tsquery, проблемам экранирования специальных символов и способам их преодоления с помощью quote_literal и пользовательского анализатора.
Содержание
- Что такое
to_tsquery - Проблемы с экранированием и двойное использование
quote_literal - Решение: использование анализатора, сохраняющего пробелы и специальные символы
- Практические примеры запросов
- Рекомендации по настройке и использованию
Полнотекстовый поиск (FTS) в PostgreSQL предоставляет мощный механизм для поиска по тексту с учётом морфологии языка, стоп‑слов и ранжирования результатов. Ключевой элемент этого механизма – функция to_tsquery, преобразующая пользовательскую строку в внутреннее представление запроса к индексу tsvector.
В Части 29286 г. обь описываются типичные трудности, возникающие при формировании таких запросов, особенно когда в поисковой фразе присутствуют специальные символы (например, :, &, кавычки) или необходимость сохранить пробелы как часть лексемы.
Что такое to_tsquery
Функция to_tsquery([config,] querytext) принимает:
config– необязательное имя конфигурации текстового поиска (например,'russian'или'english');querytext– строку, содержащую операторы&(AND),|(OR),!(NOT) и префикс:*для поиска по префиксу.
На выходе получается значение типа tsquery, которое можно использовать в операторе @@ для сопоставления с полем tsvector.
SELECT to_tsquery('russian', 'supernovae :stars & !crab');
В примере выше ищутся документы, содержащие лексему supernovae, followed by лексему stars (оператор : задаёт фразу), но не содержащие лексему crab.
Проблемы с экранированием и двойное использование quote_literal
При формировании querytext динамически (например, из пользовательского ввода) возникает необходимость экранировать специальные символы, иначе они будут интерпретироваться как операторы полнотекстового поиска. Для этого часто применяют функцию quote_literal, которая оборачивает стрение в одинарные кавычки и удваивает любые одинарные кавычки внутри.
Однако, если строка уже содержит одинарные кавычки, одинарное применение quote_literal может привести к двойному экранированию, что приводит к синтаксическим ошибкам:
-- Неправильно: двойное экранирование
SELECT to_tsquery(quote_literal(quote_literal('supernovae :stars')) & !crab);
Правильный вариант – экранировать только один раз:
SELECT to_tsquery(quote_literal('supernovae :stars') & !crab);
В Части 29286 г. обь подчёркивается, что двойное использование quote_literal необходимо лишь в случае, когда строка уже прошла через один уровень экранирования (например, при подготовке параметра в клиентском драйвере) и требуется дополнительное экранирование на уровне SQL.
Решение: использование анализатора, сохраняющего пробелы и специальные символы
Когда в поисковой фразе важны пробелы или специальные символы (например, двоеточие : для фразового поиска), стандартный анализатор может их отбросить при токенизации. Чтобы избежать потери таких символов, рекомендуется:
- Создать пользовательскую конфигурацию текстового поиска, основанную на стандартной (например,
russian), но заменить её токенизатор наsimpleилиwhitespace, который не удаляет пробелы и не меняет регистр. - Убедиться, что при индексации поле
tsvectorпостроено с использованием этой конфигурации. - При формировании запроса использовать ту же конфигурацию в
to_tsquery.
Пример создания конфигурации:
CREATE TEXT SEARCH CONFIGURATION public.my_russian ( COPY = russian ); ALTER TEXT SEARCH CONFIGURATION public.my_russian ALTER MAPPING FOR asciiword, asciihword, hword_asciipart, word, hword, hword_part WITH simple;
Теперь запрос сохранит фразу exactamente как введена:
SELECT to_tsquery('public.my_russian', '"supernovae :stars" & !crab');
Обратите внимание на двойные кавычки вокруг фразы – они обязательны, когда нужно сохранить пробелы и специальные символы как часть одного лексемы.
Практические примеры запросов
Пример 1: Простой поиск с оператором AND
SELECT *
FROM articles
WHERE to_tsvector('russian', content) @@ to_tsquery('russian', 'postgresql & full-text');
Пример 2: Фразовый поиск с сохранением пробела
SELECT *
FROM articles
WHERE to_tsvector('public.my_russian', content) @@
to_tsquery('public.my_russian', '"полнотекстовый поиск"');
Пример 3: Исключение слова с учётом регистронезависимости
SELECT *
FROM articles
WHERE to_tsvector('russian', title) @@
to_tsquery('russian', 'postgresql & !tutorial');
Пример 4: Динамический запрос с безопасным экранированием
PREPARE search_plan (text) AS
SELECT *
FROM documents
WHERE to_tsvector('russian', body) @@
to_tsquery('russian', quote_literal($1) & !'spam');
EXECUTE search_plan('PostgreSQL: лучшая СУБД');
Рекомендации по настройке и использованию
- Всегда указывайте явно конфигурацию текстового поиска в обеих функциях –
to_tsvectorпри индексации иto_tsqueryпри запросе. Это избавит от неожиданного использования default конфигурации, которая может отличаться от ожидаемой. - Для фразового поиска используйте двойные кавычки (
"...") и убедитесь, что выбранный анализатор не удаляет пробелы внутри кавычек. - При работе с пользовательским вводом экранируйте строку один раз через
quote_literal(или лучше – используйте параметризованные запросы, как в примере 4). Двойное экранирование применяйте только если вы уверены, что строка уже прошла один уровень обработки. - Тестируйте свои конфигурации на представительном наборе данных: проверьте, как обрабатываются стоп‑слова, синонимы и специальные символы.
- Регулярно обновляйте статистику (
ANALYZE) после массовых изменений в таблице, чтобы планировщик мог выбрать оптимальный план использования индексаGINна полнотекстовое поле.
В Части 29286 г. обь подробно раскрыты нюансы работы с функцией to_tsquery в PostgreSQL, включая проблемы экранирования, необходимость двойного применения quote_literal и способы сохранения пробелов и специальных символов через пользовательский анализатор. Следуя приведённым рекомендациям и примерам, вы сможете построить надёжный и эффективный полнотекстовый поиск, который корректно обрабатывает как простые ключевые слова, так и сложные фразы с пунктуацией и регистронезависимыми операторами.
Полнотекстовый поиск остаётся одним из самых мощных инструментов СУБД PostgreSQL, а правильная настройка запросов обеспечивает высокую релевантность результатов и минимум ложных срабатываний.