Анатомия анализатора: char filters, токенизатор, token filters
Когда вы индексируете документ с text-полем, Elasticsearch не кладёт строку в индекс как есть. Сначала текст проходит через анализатор — конвейер из трёх последовательных стадий. На выходе получается список токенов: нормализованных фрагментов, по которым строится инвертированный индекс. Именно анализатор решает, найдёт ли поиск по слову «бегу» документ со словом «бежит» — или нет.
Понять устройство анализатора нужно до перехода к конкретным языковым настройкам — английскому, русскому, синонимам. Всё это варианты одного и того же механизма.
Конвейер анализа: три стадии
Анализатор всегда состоит из трёх частей:
1. Char filters — обрабатывают сырую строку символ за символом, ещё до разбивки на слова.
2. Tokenizer — разрезает строку на токены. Ровно один, обязателен.
3. Token filters — нормализуют и обогащают каждый токен. Их может быть несколько.
flowchart LR
A([Сырой текст]) -->|строка| B[Char Filters]
B -->|строка| C[Токенизатор]
C -->|токены| D[Token Filters]
D -->|токены| E([Инвертированный индекс])
style A fill:#eef2ff,stroke:#6366f1
style E fill:#d4edda,stroke:#28a745Char filters и token filters необязательны — их может не быть вовсе. Токенизатор же один и только один: без него конвейер не работает.
Стадия 1: char filters
Char filters видят сырую строку до токенизации и могут изменить её любым образом. Три встроенных варианта:
| Фильтр | Что делает | Пример |
|---|---|---|
html_strip | Удаляет HTML-теги | <b>Hello</b> → Hello |
mapping | Заменяет подстроки по словарю | & → and |
pattern_replace | Заменяет по регулярному выражению | (\d+)-(\d+) → $1 $2 |
Практичный сценарий: вы индексируете статьи из CMS, которые приходят с HTML-разметкой. Без html_strip токены вроде </p> или <strong> попадут в индекс и засорят результаты.
Стадия 2: tokenizer
Токенизатор получает строку (уже обработанную char filters) и разрезает её на токены. От его выбора зависит фундаментальная гранулярность поиска.
| Токенизатор | Принцип | Результат для «Hello, world!» |
|---|---|---|
standard | По пробелам и пунктуации (Unicode) | ["Hello", "world"] |
whitespace | Только по пробелам | ["Hello,", "world!"] |
keyword | Вся строка — один токен | ["Hello, world!"] |
pattern | По regex-разделителю | задаётся явно |
standard подходит для большинства задач с европейскими языками — он удаляет пунктуацию и разбивает по словам. keyword применяется там, где строку нужно хранить и искать целиком: именно так работают keyword-поля по умолчанию.
Стадия 3: token filters
Фильтры токенов работают с потоком токенов после токенизатора. Применяются последовательно — один за другим.
| Фильтр | Что делает |
|---|---|
lowercase | Hello → hello |
stop | Удаляет стоп-слова (the, a, «и», «в») |
stemmer | Стемминг — обрезает до основы (running → run) |
synonym | Добавляет синонимы (car = automobile) |
asciifolding | Заменяет диакритику (é → e) |
Порядок фильтров имеет значение. Если поставить stop перед lowercase, фильтр не распознает стоп-слово The (с заглавной буквы) — в словаре оно записано строчными. Правильный порядок: сначала lowercase, потом stop.
Встроенный standard-анализатор под микроскопом
Анализатор standard — тот, что Elasticsearch применяет к text-полям, если маппинг не задан явно. Он устроен так:
- char filters: нет
- tokenizer:
standard - token filters:
lowercase
Строка «Quick brown FOX jumps» превращается в: ["quick", "brown", "fox", "jumps"].
Важный момент: стоп-слова в standard-анализаторе по умолчанию не удаляются — словарь стоп-слов пуст. Чтобы они убирались, нужен языковой анализатор (english, russian) или кастомный. Об этом подробнее в статьях Анализ английского текста: стемминг и стоп-слова и Анализ русского текста: морфология, стемминг, Hunspell.
Index-анализ и Search-анализ
Анализ происходит дважды, и это ключевая идея:
1. При индексации — Elasticsearch анализирует текст документа и записывает токены в инвертированный индекс.
2. При поиске — строка из запроса match тоже проходит через анализатор, прежде чем сравниваться с индексом.
Это означает: оба прохода должны давать совместимые токены. Если при индексации running превратилось в run, то поисковая строка running тоже должна превратиться в run — иначе совпадения не будет.
По умолчанию Elasticsearch использует один и тот же анализатор на обоих этапах. Но в маппинге можно задать отдельный search_analyzer. Это нужно, например, для синонимов: их лучше применять только при поиске, чтобы не раздувать индекс. Подробнее — в статье Синонимы и кастомные анализаторы.
_analyze API: смотрим под капот
Прежде чем зафиксировать анализатор в маппинге, проверьте его поведение. Эндпоинт _analyze показывает ровно то, что попадёт в индекс.
Проверить встроенный анализатор:
POST /_analyze
{
"analyzer": "standard",
"text": "The Quick Brown Fox Jumps"
}Ответ (упрощённо):
{
"tokens": [
{ "token": "the", "start_offset": 0, "end_offset": 3, "position": 0 },
{ "token": "quick", "start_offset": 4, "end_offset": 9, "position": 1 },
{ "token": "brown", "start_offset": 10, "end_offset": 15, "position": 2 },
{ "token": "fox", "start_offset": 16, "end_offset": 19, "position": 3 },
{ "token": "jumps", "start_offset": 20, "end_offset": 25, "position": 4 }
]
}Что возвращает API:
token— что попало в индексstart_offset/end_offset— позиция в исходной строке (нужна для подсветки совпадений)position— порядковый номер токена (важен дляmatch_phrase)
Проверить анализатор конкретного индекса (если индекс catalog уже создан с кастомным анализатором):
POST /catalog/_analyze
{
"analyzer": "my_analyzer",
"text": "Бегущий по волнам"
}Собрать конвейер на лету и отладить пошагово:
POST /_analyze
{
"tokenizer": "standard",
"filter": ["lowercase", "stop"],
"text": "The Quick Brown Fox Jumps"
}Последний вариант — отличный инструмент отладки: добавляйте фильтры по одному и смотрите, как меняется результат на каждом шаге. Это особенно ценно при настройке стемминга или синонимов.
_analyze — только инструмент разработки. Он не меняет индекс и не выполняет поиск: просто показывает, как анализатор преобразует конкретный текст.
Итог
Анализатор — конвейер из трёх стадий: char filters обрабатывают сырую строку, токенизатор режет её на части, token filters нормализуют каждый токен. Анализ применяется и при индексации, и при поиске — обе стороны должны быть согласованы. Проверить любой анализатор — хоть встроенный, хоть кастомный — можно в любой момент через POST /_analyze.
См. также
- Анализ английского текста: стемминг и стоп-слова
- Анализ русского текста: морфология, стемминг, Hunspell
- Синонимы и кастомные анализаторы
- Типы полей: text, keyword, числа и даты
- Инвертированный индекс и движок Lucene
- Маппинг: явный, динамический и шаблоны индексов
- Полнотекстовые запросы: match, match_phrase, multi_match