Elasticsearch Введение — 1.3 Как работает поиск?

Теперь давайте коротко обсудим, как работает поиск из внутри. Все данные в Elasticsearch хранятся в Apache Lucene как инвертированный индекс. Несмотря на то что данные хранит по факту в Apache Lucene, Elasticsearch предоставляет удобное Api для работы с этими данными.

Простой поисковой запрос

Скажем, у нас есть таблица User:

Id Имя Возраст Пол Эл. адрес
1 Иван 25 M ivan@gmail.com
2 Лида 20 F lida@gmail.com

И мы хотим найти всех пользователей с именем Иван, SQL выглядел бы так:

Запрос в Elasticsearch:

где у нас example1 — индекс, user — тип, name — поле по которому ищем. Ответ будет в формате JSON.

Запросы с использованием параметров URL лучше использовать для простых вещей. Для более сложных случаев лучше использовать запрос в формате JSON расположенном в теле POST запроса.

Api поиска очень гибкий поддерживает различные виды фильтров, сортировку, разбиение на страницы и агрегации.

Инвертированный индекс

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

  1. Страх ведет к гневу
  2. Гнев ведет к ненависти
  3. Ненависть ведет к страданиям

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

Слово Документы
страх 1
гнев 1,2
ненависти 2,3
страданиям 3
ведет 1,2,3

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

Концерт в Пушкинском парке может не состояться из-за значительных осадков

Например мы хотим посетить это концерт, но волнуемся о погоде и можем написать примерно следующее погода в Пушкинском парке или дождь в Пушкинском парке. При существующем подходе мы не сможем ответить на этот вопрос, поскольку у документа и запросов нет четкого соответствия по словам. Чтобы справиться с такой ситуацией используют разные методы, о них мы поговорим ниже.

Морфологический

Это процесс сокращения слова до его корня. Например дождь, дожди, дождик имеют один корень дождь и мягкий знак можно убрать останется дожд. Когда документ индексируется, корневое слово сохраняется в индексе вместо фактического.

Синонимы

Они нам помог не только при поиске слов с одинаковым смыслом, но и уменьшат размер индекса, устраняя различия между похожими словами.

Поиск по фразе

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

гнев 1,2
ведет 1,2,3

Из приведенных выше таблиц, слова гневи ведет существуют как в document1и document2. Чтобы поддерживать поиск фразы вместе с документом, нам также необходимо записать положение слова в документе:

Слово Документы
страх 1: 1
гнев 1: 3, 2: 1
ненависти 2: 3, 3: 1
страданиям 3: 3
ведет 1: 2, 2: 2, 3: 2

Теперь, поскольку у нас есть информация о позиции слова, мы можем выполнить поиск, если в документе есть слова в том же порядке, что и в запросе.

гнев 1: 3, 2: 1
ведет 1: 2, 2: 2

Поскольку в во втором документе слово гнев первое, а слово и ведетвторое, то есть порядок слов совпадает в запросе, то очевидно второй документ подходит лучше чем первый. С инвертированным индексом любой запрос по документам представляет собой простой поиск. Это всего лишь введение в инвертированный индекс; В реальной жизни он намного сложнее, но основы остаются прежними.

Apache Lucene

Apache Lucene — одна из самых зрелых реализаций инвертированного индекса. Lucene — полнотекстовая библиотека поиска с открытым исходным кодом. Это очень высокая производительность, полностью написанная на Java. Любое приложение, которое требует текстового поиска, может использовать Lucene. Это позволяет добавлять возможности полнотекстового поиска в любое приложение. Elasticsearch использует Apache Lucene для управления и создания своего инвертированного индекса. Чтобы узнать больше об Apache Lucene, посетите   http://lucene.apache.org/core/ .