Анализаторы и токенизация

Разбираем, как именно текст превращается в термы инвертированного индекса — то есть устройство анализатора.

Анализатор — конвейер, превращающий строку текста в набор термов; состоит из символьных фильтров, токенизатора и токен-фильтров.

Зачем

Чтобы match находил «Кофемашины» по запросу «кофемашина», текст и запрос должны проходить одинаковую обработку: разбиение на слова, нижний регистр, обрезка до основы. Эту обработку и выполняет анализатор — и при индексации, и при поиске.

Конвейер из трёх ступеней

  "Кофе, КОФЕ и чай!"
        |
  [1] char filter   -- убрать/заменить символы (напр. HTML)
        |
  "Кофе, КОФЕ и чай!"
        |
  [2] tokenizer     -- разбить на токены по границам слов
        |
  [Кофе] [КОФЕ] [и] [чай]
        |
  [3] token filters -- нижний регистр, убрать стоп-слова, стемминг
        |
  [кофе] [кофе] [чай]   --> в индекс
СтупеньЧто делает
char filterправит сырой текст до разбиения (например, выкидывает HTML-теги)
tokenizerрежет текст на токены (обычно по пробелам и пунктуации)
token filtersпреобразуют токены: нижний регистр, стоп-слова, стемминг, синонимы

Готовые анализаторы

Не нужно собирать конвейер с нуля — есть встроенные:

  • standard — по умолчанию: режет по словам, нижний регистр, базовая обработка пунктуации;
  • simple — режет по любым не-буквам, нижний регистр;
  • keyword — не режет вовсе, весь текст — один токен (для точных полей);
  • russian, english и др. — языковые: добавляют стоп-слова и стемминг для конкретного языка.

Проверить анализатор: _analyze

Лучший способ понять, что попадёт в индекс — спросить ES напрямую:

curl -X POST http://localhost:9200/_analyze \
  -H 'Content-Type: application/json' \
  -d '{ "analyzer": "standard", "text": "Кофе, КОФЕ и чай!" }'

В ответе вы увидите итоговые токены с их позициями. Этим инструментом стоит пользоваться постоянно при отладке поиска.

Как работает под капотом

При индексации поля text ES прогоняет его значение через анализатор поля и кладёт получившиеся термы в инвертированный индекс. При поиске match прогоняет строку запроса через тот же анализатор. Совпадение происходит на уровне термов: важно не как выглядел исходный текст, а какие термы из него получились. Поэтому ответ на вопрос «почему не находит» почти всегда лежит в том, какие термы реально лежат в индексе — а это показывает _analyze.

Частые ошибки

  • Разные анализаторы при индексации и поиске. Если поле проиндексировано одним анализатором, а ищется другим, термы не совпадут. По умолчанию ES использует один и тот же — не ломайте это без причины.
  • Анализатор по умолчанию для русского. standard не делает стемминг русского, поэтому «кофемашины» и «кофемашина» — разные термы. Для русского нужен анализатор russian.

Итоги

  • Анализатор — конвейер: символьные фильтры → токенизатор → токен-фильтры.
  • Один и тот же анализатор применяется при индексации и при поиске; совпадение идёт по термам.
  • Эндпоинт _analyze показывает, какие термы получаются — главный инструмент отладки.
Проверьте себя
1. Из каких ступеней состоит анализатор?
AТолько токенизатор
BСимвольные фильтры, токенизатор и токен-фильтры
CШарды, реплики и узлы
Dmatch, term и bool
2. Какой эндпоинт показывает, на какие термы разбивается текст?
A_search
B_analyze
C_mapping
D_bulk