Полнотекстовый поиск для приложений
Пользователь вводит "ноутбук леново" — ожидает релевантные результаты за миллисекунды. 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 | Фильтры "бренд", "цена" в боковой панели |
Морфология для русского: формы "ноутбук", "ноутбуки" должны находиться одним запросом — настраивается анализатором.
Поток данных
- Запись в БД — источник истины.
- Синхронизация в поисковый индекс:
- синхронно при записи (просто, риск задержки API);
- асинхронно через очередь (рекомендуется);
- CDC (change data capture) из WAL.
- Поисковый запрос — только в движок, ID → обогащение из БД при необходимости.
Идемпотентность индексации: повторное событие product_updated не должно ломать документ.
Запросы и bulk
- Поиск — query string, match phrase, fuzzy для опечаток.
- Bulk API — пачковая индексация при реиндексации каталога.
- Alias — переключение
products_v2→productsбез даунтайма.
Не индексируйте в поиск пароли и PII, если нет юридической необходимости.
Операционные риски
| Риск | Митигация |
|---|---|
| Расхождение БД и индекса | Периодическая сверка, dead-letter очередь |
| Рост индекса | TTL, архив, отдельные индексы по годам |
| Медленный агрессивный fuzzy | Лимиты, min score |
| Split-brain в кластере | Кворум, мониторинг (PACELC) |
Критерии выбора
- Нужны ли фасеты и сложный scoring?
- Объём документов > 1–10 млн?
- Допустима ли eventual consistency в выдаче?
- Есть ли команда для кластера поиска?
- Достаточно ли PostgreSQL
tsvectorна первые 2 года?
Если пункты 1–2 "нет" — начните с FTS в основной БД, не с Elasticsearch.