Основы полнотекстового поиска в ElasticSearch. Часть вторая |
||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2023-09-05 13:17 Оглавление цикла:
Это вторая статья из цикла. В первой части я рассказывал про самые базовые понятия Elasticsearch. В этом же посте разберем устройство анализа текста и немного пощупаем полнотекстовый поиск. Несколько слов про анализ текста Анализ текста — процесс преобразования оригинального текста в структурированный формат, оптимизированный под эффективное хранение и быстрый поиск. Мы уже познакомились с некоторыми типами Elasticsearch, но в этом разделе будем рассматривать только два — keyword и text. Тип text анализируется для полнотекстового поиска. Тип keyword преимущественно остается без изменений для точного поиска, сортировки и агрегации. Анализ текста происходит:
На этот процесс анализа возложены две функции: Токенизация (tokenization) — разбиение текста на более мелкие части, которые называются токенами или термами. Нормализация (normalization) — процесс, в котором токены приводятся к некой единой форме. Например, приведение к нижнему регистру. Анализатор За анализ текста в Elasticsearch отвечают анализаторы (analyzer). Внутреннее устройство анализатора: Анализатор состоит из трёх последовательных частей:
В Elasticsearch много встроенных анализаторов. Какие-то из них можно использовать прямо из коробки без какой-либо настройки. Пример встроенных анализаторов:
Character filter Этот компонент подготавливает оригинальный текст перед разбиением на токены. В Elasticsearch существует три типа фильтра:
Рассмотрим пример настройки mapping character filter в Elasticsearch. Для этого примера воспользуемся Analyze API. На языке Elasticsearch это выглядит следующим образом: И натравим character filter на текст: Фильтр успешно заменил все «ё» на «е» без учета регистра. Tokenizer Токенайзер разбивает входящий поток символов в поток токенов по их границам, используя разделитель (пробелы, знаки препинания и так далее). Помимо разбиения текста на токены, компонент ответственен за сбор информации о каждом токене: Примеры типов: <ALPHANUM> (alphanumeric), <HANGUL>, <NUM>, <SYNONYM> и т.д. Информация о позиции токена может быть использована, когда поиск требует четкой последовательности слов в документе. Знание информации о начальной и конечной позициях оригинального слова, которое этот токен представляет, может быть использовано для выделения фрагментов поиска. Например, оригинальные слова, которые соответствовали параметрам запроса, могут быть выделены HTML-тегами. Предлагаю рассмотреть несколько примеров встроенных токенайзеров. Standard tokenizer Стандартный токенайзер использует алгоритм Unicode Text Segmentation для нахождения границ токенов. Этот токенайзер включен в состав стандартного анализатора, который Elasticsearch использует по умолчанию. Разберем работу такого токенайзера на примере: Стандартный токенайзер из фразы "it's possible" вытащил два токена — it's и possible. Для разбиения токенайзер использует спецсимволы — знаки препинания, кавычки, проценты, пробелы и подобное. Стоит обратить внимание, что при разбиении апостроф сохранился. N-gram tokenizer N-gram tokenizer разбивает входящий поток символов «скользящим» окном, начало которого перемещается по мере прохождения символов. Рассмотрим принцип работы на примере: Edge n-gram tokenizer Edge n-gram tokenizer разбивает входящий поток символов «скользящим» окном, начало которого находится в начале слова. И снова пример: Token filter Token filter совершает преобразования над входящим потоком токенов следующими простыми операциями: Познакомимся с некоторыми операциями поближе. Stemming Стемминг — это процесс нахождения стеммы (основы слова). Стемминг позволяет делать поисковый движок независимым от формы слова. Небольшой пример: Все приведенные слова приводятся к единой основе. Стемминг бывает двух видов: Алгоритмический использует под капотом различные алгоритмы (porter, snowball и прочие) по поиску основы слова. Такой вид стемминга может неплохо работать из коробки, не требует много памяти и обычно быстрее, чем словарный. Из минусов нужно отметить, что бывают неожиданные результаты на особых словах или словах-исключениях. Словарный стемминг использует справочник. Такой подход позволяет обрабатывать особые слова или слова-исключения и помогает различать слова, которые пишутся схоже, но отличаются по значению, например, организация и орган. Для правильной работы справочник должен включать огромное количество слов, а также своевременно обновляться в зависимости от языковых тенденций. Очевидно, что минус такого стеммера — ощутимое потребление оперативной памяти. Предлагаю рассмотреть, как Elasticsearch справляется с русским языком. Пример: По поводу корректности работы делайте выводы сами. Отмечу, что все слова сложные и имеют два корня — "фут" и "бол". Вероятно, что для некоторых кейсов правильно приводить все слова из примера к единой стемме. Если вас не устраивает то, как Elasticsearch справляется с русским языком из коробки, то можно попробовать воспользоваться словарями для проверки орфографии — Hunspell. Просто скачиваете словарь для русского языка и указываете путь в конфигах Elasticsearch. Если даже Hunspell-словарь не исправил ситуацию, то можно посмотреть в сторону морфологических плагинов для русского языка. Тут стоит предупредить, что многие из этих плагинов больше не поддерживаются и могут не подойти под вашу версию Elasticsearch. Синонимы и графы токенов При разбиении текста на токены собирается информация о позиции каждого токена, а также сколько позиций данный токен охватывает. Эти параметры называются position и positionLength (игнорируется при индексировании). Разберем их на примерах: Скажем, у нас есть пример статьи из интернета — «Kubernetes — Service Types Overview». По дефолту Elasticsearch побьет этот документ на 4 токена и приведет их к нижнему регистру. Elasticsearch для каждого токена зафиксировал параметры position и positionLength. Все токены имеют значение positionLength равное 1, так как охватывают сами себя. Предположим, что пользователь может искать название данной статьи с помощью сокращения для слова kubernetes — k8s. Здесь нам на помощь приходят синонимы. У Elasticsearch есть synonym токен-фильтр, который может добавлять синонимы, охватывающие одну позицию. Synonym токен-фильтр добавляет пятый токен k8s, который имеет position = 0 и positionLength = 0. Новый токен, который является синонимом, ставится в параллель оригинальному слову и имеет такие же параметры. Допустим, что нам нужно настроить наш поисковый движок таким образом, чтобы он умел работать с синонимами, которые охватывают несколько позиций. У Elasticsearch есть токен-фильтр, который называется synonym graph. Он позволяет корректно работать с синонимами, которые охватывают несколько позиций — аббревиатуры, акронимы, различные термины и так далее. И снова пример статьи из интернета — «Java Garbage Collection Basics». При поиске словосочетание «Garbage Collection» можно сократить до «GC»: Elasticsearch добавляет пятый токен gc c параметрами position = 1 и positionLength = 2, то есть он охватывает два токена — garbage и collection. Мы с вами рассмотрели, как Elasticsearch добавляет новые токены в виде синонимов к уже существующему множеству. Но, к сожалению, не все так просто. Взглянем на нюансы. Подводные камни синонимов Итак, разберем тонкие моменты работы с синонимами в Elasticsearch. Для примера зададим следующие синонимы:
Далее нужно создать свой индекс в Elasticsearch. Так как это обзорная статья, то я постараюсь объяснить все параметры, которые задал для индекса и для поиска документов. Для этого создадим индекс с названием article: Начнем разбор этого JSON с маппинга: Документы имеют одно поле — name. Для данного поля устанавливаем тип text, чтобы содержимое анализировалось при поиске и индексации. Для этого поля задано два анализатора — custom_index_analyzer и search_analyzer_w_synonym_graph. Эти значения стоят в полях analyzer и search_analyzer. Первый анализатор будет использоваться при индексации документа, а второй — для полнотекстового поиска по этому полю. Теперь перейдем к настройке самих анализаторов: В поле analyzer описаны два анализатора, которые мы прописали в маппинге. Первый анализатор custom_index_analyzer состоит из стандартного токенайзера и токен-фильтра, который приводит токены к нижнему регистру. Второй анализатор search_analyzer_w_synonym_graph состоит из стандартного токенайзера и двух токен-фильтров. Первый фильтр приводит токены к нижнему регистру, а второй фильтр custom_synonym_graph_filter нужен для добавления синонимов. Настройка последнего находится в поле filter, и там указаны тип фильтра и путь к файлу с нашими синонимами. В индекс сохранены следующие документы: При индексации Elasticsearch разобьет данные документы на токены: Мы закончили настраивать наш индекс. Переходим к экспериментам. У нас есть поисковый запрос — "k8s guide". Посмотрим, как Elasticsearch разобьет его на токены: Как видите, Elasticsearch разбил поисковый запрос на токены и будет искать в индексе article все документы, которые содержат один из токенов — k8s, kubernetes и guide. Посмотрим, какие документы выдаст поисковый запрос: Пример полнотекстового поиска c добавлением простого синонима Приведенный в примере запрос (match query) в виде JSON-документа интуитивно понятный и не должен вызвать каких-либо трудностей. Его упрощенная версия приведена на рисунке (см. Query view). Результат, который выдал Elasticsearch, тоже приведен в виде JSON-документа. Из него нам нужно только поле hits, в котором перечислены подходящие документы. Запрос нам выдал ровно один документ, что и ожидалось. Рассмотрим следующий запрос — "domain name system cache": Elasticsearch добавляет пятый токен dns, который имеет параметры position = 0 и positionLength = 3. То есть новый токен охватывает три токена — domain, name и system. Посмотрим, какие документы выдаст поисковый запрос: Пример полнотекстового поиска c добавлением синонима (аббревиатуры) Единственное отличие от предыдущего match query запроса — наличие поле operator. По умолчанию Elasticsearch все токены связывает условием OR, но для разнообразия был использован AND. То есть изменился логический оператор для токена cache. Запрос нам выдал ровно один документ, что и ожидалось. Для демонстрации последнего примера внесем правки в созданный индекс: изменим тип токен-фильтра с synonym graph на synonym. Все остальные настройки остаются такими же. В этом примере хочу продемонстрировать, что такой тип токен-фильтра не умеет работать с синонимами, которые охватывают несколько позиций. Найдем все документы, в которых есть упоминание dns: Elasticsearch добавляет три новых токена — domain, name и system. Стоит обратить внимание, что такой тип фильтра не умеет корректно работать с параметром positionLength. Для всех токенов он равен единице. То есть токену аббревиатуры dns ставится в параллель токен domain, что неправильно. Посмотрим, какие документы выдаст поисковый запрос: Elasticsearch выдал три документа, причем один из них неожиданно попал в нашу выборку — «Domain-Driven Design in the era of Microservices». А все из-за неправильного значения параметра positionLength. Это в свою очередь повлияло на неправильную расстановку логических операторов между токенами в запросе. Заканчивая текущий пост, взглянем на стандартный анализатор. Стандартный анализатор Стандартный анализатор состоит из одного токенайзера и одного токен-фильтра: Стандартный анализатор разбивает содержимое на токены согласно алгоритму Unicode Text Segmentation и приводит полученные токены к нижнему регистру. В качестве примера возьмем цитату А.П. Чехова про карасей в сметане: Итак, это была вторая статья из цикла. В третьей поговорим про стандартную модель ранжирования документов в Elasticsearch. Источник: habr.com Комментарии: |
|