Анализ английского текста: стемминг и стоп-слова
В предыдущей статье мы разобрали анатомию анализатора — три стадии конвейера: char filters, токенизатор, token filters. Теперь посмотрим, как этот конвейер собран в конкретном встроенном анализаторе english, который Elasticsearch поставляет «из коробки» для английского языка.
Что такое анализатор english
Анализатор english — это предсобранный конвейер, специально настроенный под морфологию английского. В отличие от standard, который просто делит текст по пробелам и приводит к нижнему регистру, english умеет:
- убирать притяжательные суффиксы (
author's→author) - выбрасывать стоп-слова (
the,is,areи ещё несколько десятков) - сводить слова к основе через стемминг (
running→run)
Именно эти три вещи делают разницу между «найти документ ровно с этим словом» и «найти документы по смыслу, в любых словоформах».
Состав анализатора english
Char filters: нет.
Tokenizer: standard — делит по пробелам и пунктуации, удаляет знаки препинания.
Token filters (по порядку):
1. english_possessive_stemmer — убирает притяжательный суффикс: author's → author, company's → company
2. lowercase — всё в нижний регистр: Quick → quick
3. english_stop — удаляет стоп-слова: the, a, is, are, in, on…
4. english_stemmer — стемминг по алгоритму Snowball/Porter2: running → run, foxes → fox
flowchart TD
A["Исходный текст<br/>'The foxes are running'"] --> B["Tokenizer: standard<br/>[The, foxes, are, running]"]
B --> C["Filter 1: english_possessive_stemmer<br/>[The, foxes, are, running]"]
C --> D["Filter 2: lowercase<br/>[the, foxes, are, running]"]
D --> E["Filter 3: english_stop<br/>[foxes, running]"]
E --> F["Filter 4: english_stemmer (Snowball)<br/>[fox, run]"]
F --> G["Токены в инвертированном индексе:<br/>fox, run"]Порядок фильтров здесь неслучаен: сначала идёт lowercase, и только потом english_stop. Если бы стоп-слова фильтровались до приведения к нижнему регистру, слово The с заглавной буквы прошло бы мимо фильтра — в словаре стоп-слов оно записано строчными the. Это ровно тот принцип, который разобран в Анатомия анализатора: char filters, токенизатор, token filters.
Стемминг: слова к основе
Стемминг (stemming) — это обрезание слова до его корневой основы по набору правил. Алгоритм Snowball (Porter2) убирает суффиксы вроде -ing, -ed, -tion, -ness, -ly и другие.
| Исходное слово | После стемминга |
|---|---|
running | run |
dogs | dog |
connection | connect |
happiness | happi |
quickly | quick |
Пример happi показывает важную особенность: результат стемминга не обязан быть настоящим словом. happi не существует в английском, но это не проблема — в индекс попадают не слова для чтения, а служебные токены для сравнения. Главное, что happiness, happy и happily все дадут один и тот же токен happi. Значит, поиск по любому из них найдёт документы со всеми тремя формами.
Стоп-слова: выбрасываем шум
Стоп-слова — это слова, которые встречаются в языке слишком часто, чтобы нести поисковую нагрузку: артикли, предлоги, местоимения, вспомогательные глаголы. В английском это a, an, the, is, are, was, were, in, on, at, of, to и ещё несколько десятков.
Зачем их убирать? Если бы the попало в инвертированный индекс, оно оказалось бы в тысячах документов и никак не помогло бы ранжированию. При этом занимало бы место и замедляло поиск. Стоп-слова удаляются и при индексации, и при поиске — поэтому запрос the quick brown fox в итоге превратится в три токена: [quick, brown, fox].
Проверяем english через _analyze
Прежде чем привязывать анализатор к индексу, убедитесь, что он делает именно то, что вы ожидаете. Никаких предварительных настроек не нужно:
POST /_analyze
{
"analyzer": "english",
"text": "The quick brown foxes are running in the forest"
}Ответ (упрощённо):
{
"tokens": [
{ "token": "quick", "position": 1 },
{ "token": "brown", "position": 2 },
{ "token": "fox", "position": 3 },
{ "token": "run", "position": 5 },
{ "token": "forest", "position": 8 }
]
}Обратите внимание на пропуски в позициях: The (0), are (4), in (6), the (7) — удалены как стоп-слова. Поле position сохраняет исходные номера — это важно для match_phrase, подробнее в Полнотекстовые запросы: match, match_phrase, multi_match.
foxes превратилось в fox, running — в run. Это означает: запрос по слову fox найдёт документы, где написано foxes, а запрос runs найдёт документы с running — оба дают токен run.
Если хотите понять, какой именно фильтр что сделал, разберите конвейер вручную — добавляйте фильтры по одному:
POST /_analyze
{
"tokenizer": "standard",
"filter": ["lowercase"],
"text": "The quick brown foxes are running"
}Потом добавьте "english_stop" в массив filter, потом "porter_stem" — и смотрите, как меняется результат на каждом шаге. Так быстро находится точка, где поведение расходится с ожиданием.
Используем english в маппинге
Задать анализатор полю — одна строчка в явном маппинге при создании индекса:
PUT /articles
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "english"
},
"body": {
"type": "text",
"analyzer": "english"
}
}
}
}После этого запрос match автоматически применит тот же анализатор к строке поиска. Никакой дополнительной настройки не нужно:
GET /articles/_search
{
"query": {
"match": {
"body": "running dogs"
}
}
}Elasticsearch превратит running в run и dogs в dog, затем найдёт все документы, где встречаются эти токены — независимо от того, написано там run, runs, running, dog или dogs.
Когда english недостаточно
Встроенный анализатор хорош для общих задач, но у него есть пределы.
Слишком агрессивный стемминг. university → univers — может показаться перебором. В таких случаях подходит менее агрессивный стеммер kstem или minimal_english. Это решается через кастомный анализатор — подробнее в Синонимы и кастомные анализаторы.
Специфические стоп-слова домена. Для технической документации слово not вовсе не стоп-слово: «does not work» несёт другой смысл. Список стоп-слов переопределяется в кастомном анализаторе.
Синонимы. Если car и automobile должны находить одно и то же — нужен фильтр synonym. Это следующая статья: Синонимы и кастомные анализаторы.
Для русского языка принципы те же, но механизм значительно сложнее: вместо Snowball используются словарные подходы. Подробности — в Анализ русского текста: морфология, стемминг, Hunspell.
Итог
Анализатор english — четыре фильтра поверх стандартного токенизатора: убрать притяжательное 's, привести к нижнему регистру, выбросить стоп-слова, применить Snowball-стемминг. В результате запросы по одной форме слова находят документы по любой другой форме. Проверить — POST /_analyze. Подключить — одна строчка в маппинге.