Перейти к содержанию

Русский анализатор и технические обозначения

В схеме library-v1 заголовок и основной текст используют анализатор library_ru. Теперь разберём его цепочку. Результат урока — понимание того, почему формы русского слова могут совпасть, а обозначение C# требует отдельного точного поля. Научимся исследовать анализ через _analyze, прежде чем менять выдачу наугад.

Полная настройка уже включена в index.json архива. Это одна итоговая версия проекта: ранние уроки вводят её элементы последовательно. Анализатор и будущие ответы не проверялись исполнением. Официальная документация русского анализатора послужила источником состава фильтров, а пример библиотеки и выбор защищённых слов относятся к нашему проекту.

Сначала токены, затем преобразования

Анализ начинается с tokenizer. Он определяет границы отдельных токенов в исходной строке. После него фильтры изменяют поток: приводят регистр, убирают стоп-слова, отмечают защищённые термы и выполняют стемминг. Порядок существенен, поскольку поздний фильтр видит результат предыдущего, а не произвольную исходную строку.

Фрагмент settings.analysis ниже содержит полный объект нашего анализатора и используемые фильтры. В составе index.json рядом также определён нормализатор для точных значений:

{
  "filter": {
    "ru_stop": {"type": "stop", "stopwords": "_russian_"},
    "ru_stem": {"type": "stemmer", "language": "russian"},
    "protected_terms": {
      "type": "keyword_marker",
      "keywords": ["http", "redis", "opensearch", "node"]
    }
  },
  "analyzer": {
    "library_ru": {
      "type": "custom",
      "tokenizer": "standard",
      "filter": ["lowercase", "ru_stop", "protected_terms", "ru_stem"]
    }
  }
}

lowercase расположен перед списком защищённых слов, поэтому в списке используем нижний регистр. keyword_marker помечает уже существующий токен так, чтобы стеммер не менял его. Он не возвращает удалённые знаки пунктуации и не склеивает несколько токенов обратно в исходное название. Если tokenizer разделил выражение, защита терма не отменяет это решение.

Стемминг сокращает разные формы слова к связанному поисковому представлению. Это полезно для «запрос», «запросы», «запроса», но не является полноценным пониманием смысла предложения. Два разных слова способны получить одинаковое или похожее представление, а синонимы без специальных правил останутся различными. Поэтому не будем описывать языковой анализ как семантический поиск.

Наблюдение через Analyze API

Перед первым импортом исследуем строку «HTTP и кеширование запросов». Для читателя предусмотрена команда управления:

python manage.py analyze library-v1 "HTTP и кеширование запросов"

Она отправляет POST /library-v1/_analyze с именем library_ru и исходным текстом. Ожидаемый ответ содержит массив токенов, позиции и границы в исходной строке. Важный эффект — приведение HTTP к нижнему регистру, исключение служебного слова и обработка русских форм. Конкретное написание всех стемов нужно прочитать в ответе собственной выбранной версии, а не угадывать по человеческой морфологии.

Повторите исследование для «запроса» и «запросы». Сопоставление токенов даёт объяснение будущего совпадения документов. Если токены различаются, проблема находится до ранжирования: увеличение веса заголовка не создаст отсутствующее совпадение. Такой порядок исследования позволяет отделить разбор текста от оценки уже найденных документов.

У Analyze API есть и практическая граница. Оно показывает результат анализа выбранной строки, но не доказывает качество всего поиска. В настоящем запросе участвуют несколько полей, фильтры и ограничения результата. Строка может давать разумные токены, но нужный документ окажется исключён по видимости или рубрике. Поэтому сохраняем связь наблюдения с конкретным полем и условиями.

Название языка не равно естественному слову

В корпусе есть «Node.js и HTTP» и «C# и HTTP». Читатель может искать имя языка с пунктуацией, а разбор обычного текста обращаться с пунктуацией как с границами. Для такого случая уже введено поле identifiers. Оно хранит точные значения node.js и c# с нормализацией регистра. Это отдельный канал совпадения, а не исправление русского стеммера.

Поле body.technical использует анализатор standard без русского стемминга. Оно помогает сохранить обычные технические слова в ином поисковом представлении. Но и стандартный tokenizer не даёт обещания хранить любое обозначение целиком. Поэтому наличие второго текстового поля не заменяет явных точных идентификаторов для названий, где знаки имеют значение.

Можно добавить node в защищённые слова и решить, что Node.js теперь защищён целиком. Это ошибочный вывод: список содержит отдельный токен, а не произвольную исходную подстроку. Правильное наблюдение — изучить поток токенов и сопоставить его с целью. Для точного обозначения используем keyword; для слов внутри технического объяснения сохраняем текстовый поиск.

У двойного представления есть цена. Основной текст индексируется дважды, поэтому увеличиваются поисковые структуры и объём работы при записи. В нашей маленькой библиотеке это сознательная учебная развилка. Для большого корпуса стоит обосновать, какие поля действительно нужны контрольным запросам. Нельзя объявлять любое добавленное подполе бесплатным улучшением качества.

Изменение цепочки требует нового содержимого индекса

Предположим, редактор решил добавить ещё одно защищённое слово. Новая настройка должна влиять и на будущие запросы, и на ранее проиндексированные записи. Изменить только анализ запроса недостаточно: старые термы останутся подготовленными по прежним правилам. Получится несовпадение представлений, которое трудно объяснить через текст исходной статьи.

Практический путь — создать library-v2 с изменённой схемой, повторно обработать документы и переключить alias после проверки. Позднее изучим это как отдельную операцию. Сейчас важно заметить зависимость: анализатор относится к версии индекса. Он не является настройкой интерфейса, которую можно без последствий менять при каждом запросе пользователя.

Не добавляем автоматический fuzzy-поиск ко всем техническим обозначениям. Опечатка в обычном слове и изменение C# на C имеют разный предметный смысл. Приём допускающий приблизительное совпадение способен вернуть документы о другой технологии. Сначала нужен набор примеров ожиданий, затем отдельное правило для конкретного поля, а не универсальное расширение запроса.

Исследуйте также строку, состоящую только из стоп-слов. После анализа полезных токенов может не остаться, хотя внешняя проверка видит непустой ввод. Это разные уровни проверки: один подтверждает форму строки, другой определяет её поисковое представление. Наш договор не превращает такой ввод автоматически в обзор всей библиотеки. Нулевой результат или отдельное сообщение о слишком общей строке предпочтительнее неожиданного раскрытия всех документов.

Список стоп-слов тоже влияет на предметную задачу. Короткое служебное слово иногда входит в техническое название или цитату, где его исчезновение меняет намерение. Если такое название важно корпусу, сначала добавьте контрольный случай, затем выберите отдельное поле или другую цепочку. Изменение общего русского анализа ради одного названия затрагивает все документы и запросы.

Ожидаемый результат урока — объяснимая цепочка преобразований и два разных договора поиска: языковой текст и точные обозначения. Для упражнения составьте пары «HTTP/http», «запрос/запросы», «C#/C». Для каждой пары укажите поле, в котором хотите совпадение, и основание решения. В следующем уроке загрузим подготовленный корпус через Bulk API, сохранив возможность увидеть ошибки отдельных записей.

Оглавление серии