Перейти к основному содержимому

Полнотекстовый поиск для приложений

Разработчику Архитектору

Пользователь вводит "ноутбук леново" — ожидает релевантные результаты за миллисекунды. LIKE '%ноутбук%' в SQL на миллионах строк — не решение. Для текста, ранжирования и опечаток нужен полнотекстовый поиск (FTS).


Уровни решения

ПодходКогда достаточноОграничения
B-tree + префиксАвтодополнение по кодуНе полнотекст
FTS в PostgreSQL / MySQLОдин источник правды, умеренная нагрузкаСложная кластеризация, меньше фасетов "из коробки"
Elasticsearch / OpenSearchБольшой каталог, агрегации, гибкий scoringОтдельный кластер, синхронизация с БД
Meilisearch / ManticoreБыстрый старт, typo-toleranceМеньше экосистема enterprise
MongoDB text indexУже на документной моделиСлабее аналитика чем ES

Справочник по стеку ELK в эксплуатации: DevOps — Elasticsearch.


Базовые понятия

ТерминСмысл
ДокументЕдиница индексации (товар, статья, тикет)
ИндексИменованный набор документов
АнализаторТокенизация, стемминг, стоп-слова ("и", "в")
Inverted indexСлово → список document id
Score / BM25Релевантность выдачи
Facet / aggregationФильтры "бренд", "цена" в боковой панели

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


Поток данных

  1. Запись в БД — источник истины.
  2. Синхронизация в поисковый индекс:
    • синхронно при записи (просто, риск задержки API);
    • асинхронно через очередь (рекомендуется);
    • CDC (change data capture) из WAL.
  3. Поисковый запрос — только в движок, ID → обогащение из БД при необходимости.

Идемпотентность индексации: повторное событие product_updated не должно ломать документ.


Запросы и bulk

  • Поиск — query string, match phrase, fuzzy для опечаток.
  • Bulk API — пачковая индексация при реиндексации каталога.
  • Alias — переключение products_v2products без даунтайма.

Не индексируйте в поиск пароли и PII, если нет юридической необходимости.


Операционные риски

РискМитигация
Расхождение БД и индексаПериодическая сверка, dead-letter очередь
Рост индексаTTL, архив, отдельные индексы по годам
Медленный агрессивный fuzzyЛимиты, min score
Split-brain в кластереКворум, мониторинг (PACELC)

Критерии выбора

  1. Нужны ли фасеты и сложный scoring?
  2. Объём документов > 1–10 млн?
  3. Допустима ли eventual consistency в выдаче?
  4. Есть ли команда для кластера поиска?
  5. Достаточно ли PostgreSQL tsvector на первые 2 года?

Если пункты 1–2 "нет" — начните с FTS в основной БД, не с Elasticsearch.


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