Поиск на крупных платформах: как работает Elasticsearch и что такое Typesense
СОДЕРЖАНИЕ
Почему обычная база данных не справляется с поиском
Как устроен поиск внутри крупных сервисов — общая архитектура
Elasticsearch: для чего создан и где применяется
Как работает поиск в Elasticsearch — от запроса до результата
Typesense: быстрый поиск для разработчиков без DevOps-нагрузки
Elasticsearch vs Typesense — в чем разница и что выбрать
Когда интернет-магазин запускает строку поиска — за ней стоит отдельный движок, никак не связанный с основной базой данных. Именно он решает, что показать первым по запросу «кроссовки найк 42» и как не потерять результат, если пользователь написал «кросовки». Разберем, как это работает изнутри, чем различаются популярные решения и в каких ситуациях что имеет смысл использовать.
Почему обычная база данных не справляется с поиском
Реляционные базы данных умеют искать — через оператор LIKE или встроенный полнотекстовый поиск. На таблице в 50 000 строк это работает нормально. При переходе к миллиону записей начинаются проблемы: запрос сканирует всю таблицу, время ответа растет до секунд, а при одновременных обращениях от тысяч пользователей — система ложится.
Дело в архитектуре. SQL-таблица хранит данные строками — для поиска приходится перебирать все подряд. Специализированные поисковые движки хранят данные иначе: каждое слово знает, в каких документах оно встречается. Это называется инвертированным индексом.
Как устроен поиск внутри крупных сервисов — общая архитектура
Поисковый движок — это не одна функция, а конвейер из нескольких этапов. Пользователь вводит запрос, движок разбирает его, находит подходящие документы и сортирует по релевантности. Звучит просто. На практике каждый шаг нетривиален.
Инвертированный индекс: как это работает на практике
Представьте предметный указатель в конце книги: слово «архитектура» → страницы 12, 47, 203. Инвертированный индекс работает ровно так же, только вместо страниц — идентификаторы документов. При индексировании движок проходит по всем текстам, разбивает их на слова (токены) и строит эту карту.
Запрос «как устроен поиск» превращается в три токена: «как», «устроен», «поиск». Движок находит документы, где есть каждый из них, объединяет списки и ранжирует. Все это занимает миллисекунды — потому что не нужно читать сами документы, только индекс.
Токенизация и нормализация запросов
Токенизатор разбивает фразу на токены по пробелам и знакам препинания. Дальше включается нормализация: стемминг (отсечение окончаний — «кроссовки» → «кроссовк»), лемматизация (приведение к словарной форме), удаление стоп-слов («и», «в», «на»). Это позволяет найти «купить кроссовки» по запросу «кроссовок недорого» — токены пересекаются после нормализации.
Elasticsearch: для чего создан и где применяется
Elasticsearch появился в 2010 году. Shay Banon писал его как более удобную обертку над Apache Lucene — Java-библиотекой полнотекстового поиска, которой к тому времени было уже 10 лет. Lucene мощная, но сложная в настройке. Elasticsearch добавил REST API, горизонтальное масштабирование и простую кластеризацию.
Сегодня Elasticsearch — часть стека ELK (Elasticsearch + Logstash + Kibana). Типичные сценарии: поиск по логам в DevOps, полнотекстовый поиск на сайтах с миллионами документов, аналитика по событиям. Его используют Wikipedia, GitHub, Netflix — там, где объемы данных измеряются терабайтами и нужна горизонтальная масштабируемость.
У Elasticsearch есть и ограничения. JVM-база означает большой footprint по памяти — рабочий кластер стартует от 4–8 ГБ RAM. Настройка маппинга и шардов требует понимания внутренней архитектуры, иначе легко получить медленный кластер или Out Of Memory при пиковых нагрузках.
Как работает поиск в Elasticsearch — от запроса до результата
Цикл обработки запроса состоит из нескольких шагов:
- Клиент отправляет Query DSL (JSON-запрос) на координирующую ноду кластера
- Нода рассылает запрос на все шарды, где хранятся документы
- Каждый шард локально ищет по своему Lucene-индексу и возвращает top-N результатов с оценками
- Координирующая нода объединяет результаты, финально ранжирует и возвращает клиенту
Ранжирование по умолчанию работает по алгоритму BM25 (Best Match 25) — улучшенный вариант TF-IDF. Он учитывает частоту слова в документе, редкость слова по всему индексу и длину документа. Чем реже слово встречается в коллекции, тем выше его вес при совпадении.
Фасетный поиск реализован через aggregations — параллельно с поиском движок считает статистику по полям: сколько товаров в каждой категории, диапазоны цен, популярные бренды. Это то, что формирует фильтры на боковой панели в интернет-магазинах.
Typesense: быстрый поиск для разработчиков без DevOps-нагрузки
Typesense появился в 2016 году. Написан на C++ — не потому что это модно, а потому что цель была конкретной: время ответа менее 50 миллисекунд на любых разумных объемах данных без дополнительной настройки.
Главная особенность — встроенная устойчивость к опечаткам (typo tolerance). Запрос «кросовки» даст те же результаты, что «кроссовки» — движок автоматически ищет варианты в пределах редакционного расстояния. Для e-commerce и поиска по каталогу это критично: пользователи ошибаются, и терять их на опечатке — дорого.
Typesense значительно проще в развертывании, чем Elasticsearch. Один бинарник, минимум конфигурации, есть Typesense Cloud как managed-сервис. Платит за это ограниченной масштабируемостью при терабайтных объемах и менее гибкой системой анализа текста.
Elasticsearch vs Typesense — в чем разница и что выбрать
|
Параметр |
Elasticsearch |
Typesense |
|
Год выпуска |
2010 |
2016 |
|
Язык реализации |
Java (Apache Lucene) |
C++ |
|
Среднее время ответа |
50–200 мс при настройке |
< 50 мс из коробки |
|
Typo tolerance |
Требует настройки fuzzy |
Встроенная, работает по умолчанию |
|
Минимальный RAM |
4–8 ГБ для кластера |
512 МБ для старта |
|
Масштабируемость |
До петабайт (горизонтально) |
До сотен ГБ |
|
Сложность настройки |
Высокая (маппинг, шарды, JVM) |
Низкая (YAML-конфиг) |
|
Сценарий применения |
Логи, аналитика, корпоративный поиск |
Каталоги, e-commerce, SaaS-поиск |
|
Лицензия |
Elastic License 2.0 (с 2021) |
Apache 2.0 (open-source) |
Если проект — стартап с каталогом до 10 млн документов и нет отдельного DevOps-инженера, Typesense быстрее запустить и дешевле поддерживать. Если нужен анализ логов, сложные агрегации или объемы данных под терабайт — Elasticsearch оправдан, несмотря на сложность.
Другие движки: Meilisearch, Solr, OpenSearch
Meilisearch (2018, написан на Rust) — ближайший конкурент Typesense. Такая же ставка на скорость и простоту, похожая typo tolerance. Разница в деталях: у Meilisearch чуть менее гибкие фасеты, но более простой API. Лицензия MIT делает его популярным в open-source проектах.
Apache Solr существует с 2004 года — старейший из живых. Тоже строится на Lucene, конкурент Elasticsearch в энтерпрайз-сегменте. Богатая экосистема, много документации, но сложнее в оркестрации кластера и менее активное развитие в последние годы.
OpenSearch — форк Elasticsearch 7.10, созданный AWS в 2021 году после смены лицензии Elastic. Функционально почти идентичен ES, но под Apache 2.0. Хороший выбор для тех, кто уже сидит на AWS и хочет полностью открытую лицензию.
FAQ — частые вопросы о поисковых движках
Что такое инвертированный индекс простыми словами?
Словарь наоборот: не «документ → слова», а «слово → документы, где оно встречается». Именно это позволяет искать за миллисекунды по миллионам текстов.
Можно ли использовать Elasticsearch бесплатно?
Да. Базовые функции доступны бесплатно под Elastic License 2.0. Ограничения касаются коммерческого использования в SaaS-продуктах — встроить ES в свой облачный сервис и продавать нельзя без лицензионного соглашения.
Сколько документов выдерживает Typesense?
Несколько сотен миллионов документов — при условии достаточного RAM, так как Typesense держит индекс полностью в памяти. Типовой проект на 5–10 млн товарных карточек работает стабильно на сервере с 8–16 ГБ RAM.
Нужен ли отдельный поисковый движок для небольшого сайта?
До 50 000 документов — скорее нет, встроенный поиск CMS справится. При большем объеме или требованиях к скорости и релевантности — да, стоит выделить под поиск отдельный сервис.
Как поисковый движок обрабатывает русский язык?
Через анализаторы — наборы токенизаторов и фильтров под конкретный язык. Для русского в Elasticsearch есть морфологический анализатор (плагин russian_morphology). Typesense с русским работает, но морфология слабее — стемминг проще, чем полная лемматизация.
Что такое BM25 и почему он лучше TF-IDF?
BM25 — это TF-IDF с двумя поправками: насыщение частоты (дополнительные вхождения слова в длинном документе дают все меньший прирост оценки) и нормализация по длине документа. В результате короткий точный ответ не проигрывает длинной статье только потому, что в ней слово встречается чаще.