Базы данных

Full-text Search: Elasticsearch

GitHub имеет 330 миллионов репозиториев. Поиск "django authentication middleware" по всему коду мира возвращает результаты за <100ms. Это невозможно с LIKE в PostgreSQL. Elasticsearch с инвертированным индексом и 28 миллиардами документов кода делает это реальным.

  • **GitHub**: Elasticsearch для поиска по коду, issues, commits - 28 млрд документов, <100ms
  • **Wikipedia**: Elasticsearch для поиска по 6+ миллионам статей на 300+ языках
  • **Shopify**: Elasticsearch для поиска товаров - 10+ млрд позиций с BM25 + popularity boost

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

Инвертированный индекс - структура данных для полнотекстового поиска. Как индекс в конце книги: слово -> список документов где оно встречается. При запросе "elasticsearch tutorial" находим intersection документов содержащих оба слова. B-Tree индекс PostgreSQL ищет точные совпадения; инвертированный - по токенам.

Elasticsearch хранит инвертированный индекс в Lucene segments. Каждый shard - один Lucene индекс с несколькими segments. Новые документы сначала в memory buffer, потом flush в новый segment. Merge segments фоново - уменьшает их количество и освобождает место от deleted docs.

Запрос "quick brown fox" в Elasticsearch с AND операцией. Документ "The quick red fox jumps" совпадёт?

Analyzers и Mapping

Analyzer преобразует текст в токены при индексировании и поиске. Состоит из: character filter (удалить HTML tags), tokenizer (разбить на слова), token filter (lowercase, stemming, stop words). Mapping - схема индекса: типы полей, какой analyzer использовать.

text vs keyword в Elasticsearch: text анализируется (для полнотекстового поиска), keyword нет (для exact match, aggregations, sorting). "New York" как text -> ["new", "york"]. Как keyword -> "New York". Часто нужны оба: multi-field mapping.

Поле status содержит значения: "active", "inactive", "banned". Какой тип mapping использовать?

Query DSL

Elasticsearch Query DSL - JSON-based query language. Два типа запросов: query context (влияет на relevance score, используется для full-text search) и filter context (binary match/no-match, быстрее, кешируется).

filter context автоматически кешируется Elasticsearch. Популярные фильтры (status=published) хранятся в memory. Это главная причина выносить static conditions в filter, а не must.

Запрос ищет статьи по тексту (с relevance) и фильтрует по дате публикации. В каком context должно быть условие на дату?

Relevance Scoring: BM25

BM25 (Best Match 25) - алгоритм scoring по умолчанию в Elasticsearch 5+. Учитывает: TF (term frequency - сколько раз термин встречается в документе), IDF (inverse document frequency - насколько редкий термин), длину документа (длинные документы штрафуются).

Shopify использует Elasticsearch для поиска по 10+ миллиардам товаров. Function score query добавляет boost за популярность товара, продажи, рейтинг. Финальный score = BM25 relevance * popularity_factor.

Документ A содержит слово "search" 10 раз. Документ B - 1 раз, но слово "search" редко встречается в корпусе. BM25 даст какой результат?

Архитектура кластера Elasticsearch

Elasticsearch кластер: индекс делится на shards (горизонтальное масштабирование), каждый shard имеет replicas (HA + read scaling). Узлы: master (управление кластером), data (хранение shards), coordinating (routing запросов). При поиске: coordinating node рассылает запрос на все shards, собирает результаты, merge-sort, возвращает топ-N.

Elasticsearch index aliases: индексы можно переименовывать через aliases без downtime. Zero-downtime reindexing: создать новый индекс, перенести данные через _reindex API, переключить alias. Пока переключение - трафик идёт на старый индекс.

Elasticsearch - основная БД для хранения данных

Elasticsearch - поисковый движок, не БД. Нет транзакций, нет строгой консистентности. Используется как дополнение к основной БД (PostgreSQL, MongoDB) для поиска, не вместо неё.

Данные теряются при сетевых разделах (split-brain), нет ACID, нет referential integrity. Стандартный паттерн: PostgreSQL как источник истины, синхронизация в Elasticsearch для поиска через CDC или Kafka.

Elasticsearch кластер 3 ноды, индекс 3 primary shards с 1 replica. Нода упала. Что произойдёт?

Итоги

  • **Инвертированный индекс**: токен -> список документов; analyzer преобразует текст в токены при индексации и поиске
  • **Query vs Filter context**: match/must для relevance score, term/filter для exact match - filter кешируется
  • **BM25**: TF + IDF + field length normalization; explain API показывает как считается score

Связанные темы

Elasticsearch часто используется вместе с другими БД:

  • Polyglot Persistence — Elasticsearch - search layer поверх PostgreSQL или MongoDB как источника истины
  • Vector Databases — Elasticsearch 8.x поддерживает vector search для semantic similarity
  • Мониторинг — Kibana + Elasticsearch - стандартный стек для log analytics (ELK Stack)

Вопросы для размышления

  • Как реализовать zero-downtime reindexing когда нужно изменить mapping существующего индекса?
  • Приложение хранит товары в PostgreSQL. Как синхронизировать с Elasticsearch при UPDATE?
  • Когда достаточно PostgreSQL full-text search вместо Elasticsearch?

Связанные уроки

  • alg-24-kmp
Full-text Search: Elasticsearch

0

1

Войти