Обработка кириллицы и специальных символов в Elasticsearch и SQL СУБД

Устали от сбоев из-за кириллицы и знаков препинания? Разбираем ловушки query_string и даем рабочие рецепты для Elasticsearch, MySQL и SQL Server.

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

Современные системы поиска и хранения данных часто сталкиваються с необходимостью корректно обрабатывать запросы, содержащие кириллические символы, знаки препинания и другие специальные знаки. В этой статье мы рассмотрим типичные проблемы, возникающие при работе с такими символами в Elasticsearch, SQL Server, MySQL и других СУБД, а также предложим практические решения.

Elasticsearch и query_string

В Elasticsearch запрос query_string чувствителен к специальным символам, таким как дефис (-), точка (.), слэш (/) и т.д. Если их не экранировать, они могут восприниматься как операторы логики (AND, OR, NOT) или как части анализируемого текста.

Пример проблемного запроса

GET /my_index/_search
{
 "query": {
 "bool": {
 "must": [
 {
 "query_string": {
 "query": "lr-",
 "fields": ["title", "description"]
 }
 }
 ]
 }
 }}

Здесь дефис воспринимается как оператор NOT, поэтому документы, содержащие именно строку lr-, могут не попасть в результат.

Как экранировать специальные символы

  • Обратный слеш () перед каждым специальным символом:
  • "query": "lr\-"
    
  • Использовать simple_query_string с флагом default_operator: "AND" и отключить анализ специальных символов:
  • "simple_query_string": {
     "query": "lr-",
     "fields": ["title", "description"],
     "default_operator": "AND",
     "flags": "ALL"
     }
    
  • Создать собственный анализатор, который сохраняет дефис как часть токена (например, whitespace + keyword фильтр).

Рекомендации

  1. Для полей, где важна точное совпадение (например, коды, артикулы), используйте keyword тип поля.
  2. Если нужно выполнять полнотекстовый поиск с учётом кириллицы, задайте подходящий analyzer (например, russian или пользовательский с icu_tokenizer).
  3. Всегда экранируйте пользовательский ввод перед передачей в query_string (можно воспользоваться готовыми библиотеками, такими как elasticsearch-dsl в Python).

Поиск кириллических символов в SQL Server

В Microsoft SQL Server поиск по кириллице может давать неожиданные результаты из‑за различий в коллациях и наборов символов.

Типичная ошибка

SELECT *
FROM tablename
WHERE column LIKE '%[^A-Za-z0-9 /]%';

Такой запрос возвращает все строки, содержащие любые символы, отличные от латинских букв, цифр, пробела и слэша – то есть фактически всё, что не является ASCII.

Правильный подход

  • Указать явную коллацию, поддерживающую кириллицу, например Cyrillic_General_CI_AS:
  • SELECT *
    FROM tablename
    WHERE column COLLATE Cyrillic_General_CI_AS LIKE N'%а%';
    
  • Использовать префикс N для unicode‑строк, иначе SQL Server может выполнить неявное преобразование и потерять данные.
  • Для поиска по диапазону кириллических букв можно воспользоваться:
  • WHERE column COLLATE Cyrillic_General_CI_AS LIKE N'[А-Я]%';
    

Полезные функции

  • COLLATE – меняет коллацию только для данного выражения.
  • CHARINDEX и PATINDEX работают с unicode, если передать N' строку.
  • При необходимости можно создать вычисляемый столбец с COLLATE Cyrillic_General_CI_AS и построить на нём индекс для ускорения поиска.

MySQL: поиск с учётом пунктуации

В MySQL оператор LIKE traktирует символы пунктуации как обычные символы, однако при использовании регулярных выражений (REGEXP) или полнотекстового поиска (FULLTEXT) могут возникать нюансы.

Найти строки, содержащие дефис или апостроф

SELECT *
FROM articles
WHERE title LIKE '%-%' -- дефис
 OR title LIKE '%''%'; -- апостроф (нужно экранировать)

Исключить пунктуацию из поиска

Если нужно игнорировать пунктуацию, можно воспользоваться функцией REPLACE:

SELECT *
FROM articles
WHERE REPLACE(REPLACE(title, '-', ''), '''', '') LIKE '%искомое%';

Полнотекстовый поиск и стоп‑слова

По умолчанию MySQL рассматривает дефис как разделитель слов, поэтому фраза П‑тинаки будет индексироваться как два отдельных токена П и тинаки. Чтобы избежать этого:

  • Изменить набор символов индекса (ft_stopword_file) или использовать пользовательский парсер.
  • Либо хранить такие фразы в отдельном поле с типом CHAR или VARCHAR и выполнять поиск через LIKE.

Общие рекомендации по работе со специальными символами

  1. Определите, нужен ли вам точный match или полнотекстовый поиск. Для точного совпадения используйте поля типа keyword (Elasticsearch), CHAR/VARCHAR с соответствующей коллацией (SQL Server) или BINARY (MySQL).
  2. Всегда экранируйте пользовательский ввод перед передачей в языки запросов (query_string, LIKE, REGEXP).
  3. Выбирайте коллацию/анализатор, соответствующую языку данных (например, russian для Elasticsearch, Cyrillic_General_CI_AS для SQL Server, utf8mb4_unicode_ci для MySQL).
  4. Тестируйте запросы на реальных наборах данных, включающих как типичные, так и граничные случаи (с дефисами, апострофами, слэшами, эмодзи и т.д.).
  5. При необходимости создавайте отдельные поля для хранения «чистого» варианта строки (без пунктуации) и используйте их для фильтрации, оставляя оригинальное поле для вывода.

Корректная обработка русских и специальных символов в поисковых запросах требует понимания того, как конкретная СУБД или поисковый движок интерпретирует эти знаки. Применяя экранирование, правильные коллации/анализаторы и, при необходимости, отдельные поля для хранения нормализованных данных, вы сможете избежать ложных отрицательных и положительных результатов и обеспечить предсказуемую работу поиска в ваших приложениях.

Если у вас остались вопросы по конкретным сценариям (например, настройка анализатора для Elasticsearch с поддержкой «дефис‑как‑часть‑слова» или создание индекса по коллации в SQL Server), не стесняйтесь задавать их – мы с радостью поможем!