Настройка Elasticsearch для поиска в мобильном приложении
Нативный поиск по базе данных через LIKE '%query%' не работает для продукта с более чем несколькими тысячами записей: медленно, нет релевантности, нет подсветки совпадений, нет полнотекстового поиска с морфологией. Elasticsearch решает все эти проблемы, но требует правильной настройки на стороне сервера и грамотной интеграции в мобильном клиенте.
Архитектура: мобильное приложение не обращается к ES напрямую
Главное правило: мобильный клиент никогда не делает запросы напрямую к Elasticsearch. Всегда через backend API. Причины — безопасность (не раскрывать структуру индекса и учётные данные), возможность кэширования на сервере, контроль нагрузки.
Типичная схема: мобильное приложение → GET /api/search?q=кроссовки&category=sport&page=1 → Laravel/Node backend → Elasticsearch → ответ с пагинацией и метаданными.
Настройка индекса
Для русскоязычного контента обязателен анализатор с морфологией. Используем плагин analysis-morphology (от Артефакт) или analysis-russian (встроен в ES). Без морфологии поиск «кроссовки» не найдёт «кроссовок» или «кроссовка».
Пример маппинга поля с русским анализатором:
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "russian",
"fields": {
"keyword": { "type": "keyword" }
}
}
}
}
}
Поле keyword нужно для сортировки и агрегаций — text для этого не подходит.
Что важно для мобильного UX
Подсказки при вводе (autocomplete). Реализуем через completion suggester или search_as_you_type тип поля. Второй проще в настройке и хорошо работает для коротких запросов:
"title": {
"type": "search_as_you_type"
}
Запросы идут при каждом изменении поля с debounce 300ms. Показываем не более 5-7 подсказок.
Фасетный поиск (фильтры). Агрегации ES позволяют получать количество товаров в каждой категории/бренде одним запросом. В мобильном приложении это нижний шит с фильтрами — значения чипов обновляются при каждом изменении фильтра без повторного запроса (используем cached aggregations).
Релевантность и ранжирование. function_score запрос позволяет повысить рейтинг новых товаров, товаров с высоким рейтингом или персонализированных результатов. Для e-commerce типичная формула: базовый текстовый score × boost за популярность × decay-функция по дате.
Пагинация. Стандартный from/size работает только до 10 000 результатов (ограничение index.max_result_window). Для курсорной пагинации используем search_after с sort по уникальному полю. В мобильном приложении это бесконечный скролл без кнопки «следующая страница».
Оффлайн-поиск
ES требует сетевого подключения. Для базового офлайн-поиска: кэшируем последние результаты в SQLite, поиск по кэшу через FTS5 (CREATE VIRTUAL TABLE ... USING fts5). Качество хуже, но работает без сети.
Мониторинг и производительность
Медленные запросы к ES (более 500ms) нужно логировать. На сервере включаем slowlog — ES сам пишет в лог запросы дольше порога. В мобильном приложении отображаем skeleton-заглушки пока идёт поиск, и показываем «Поиск занимает больше времени, чем обычно» если запрос не вернулся за 3 секунды.
Сроки: настройка индекса ES с русской морфологией, интеграция search API и базовый UI поиска — 1-2 недели. Фасетный поиск, автодополнение и офлайн-кэш — 3-4 недели.







