Поиск по событиям и рынкам: отдельный индекс чтения
Основной API события и поиск решают разные задачи. Разбираем отдельную поисковую проекцию для команд, турниров и рынков, её обновление дельтами и контроль свежести результатов.

Поиск — другая форма чтения
API страницы события оптимизирован под известный event_id. Поиск начинается с текста и должен быстро сузить множество. Пытаться каждый раз обходить основной catalog API с фильтрами обычно означает смешать два разных read-pattern.
Проекция из нормализованного каталога
Indexer получает изменения события/рынка и собирает поисковый документ: нормализованное имя, aliases, tournament, sport, start_at, статус и routing id. UI получает компактный результат и затем открывает обычную страницу по internal id.
Свежесть против стоимости переиндексации
Не каждое изменение коэффициента должно менять search document. В индекс идут поля, влияющие на discoverability и availability. Live price остаётся в market API. Это отделяет высокочастотный поток от относительно спокойного каталога.
Нормализация текста отдельно от идентификаторов
Транслитерация, aliases и синонимы помогают поиску, но не являются системой сопоставления сущностей. Search может показать два похожих результата; identity resolver не имеет права объединять их только из-за совпавшего текста.
Нулевой результат из-за отставшего индекса
Если новое событие ещё не попало в индекс, навигация по турниру должна оставаться доступной. Поиск не должен быть единственной дверью в контент. Для критических страниц полезен direct route по internal id.
Что включать в поисковый документ
Поисковая проекция должна отвечать на пользовательский запрос, а не повторять всю доменную модель. Обычно достаточно стабильного identity, названия, алиасов, турнира, спорта, статуса доступности и нескольких полей для ранжирования. Тяжёлые подробности события можно дочитать по ID после выбора результата.
Так индекс остаётся компактным и быстрее обновляется. Отдельно стоит хранить версию каталога или timestamp проекции: если поиск сильно отстал, лучше показать ограниченный fallback или предупредить о неполных результатах, чем уверенно возвращать устаревшую выдачу.
- Разделять нормализованный текст для поиска и исходное отображаемое название.
- Измерять zero-result rate по языкам, видам спорта и типам сущностей.
- Удаление и закрытие события должны попадать в индекс так же надёжно, как создание.
Поиск обязан уметь честно устаревать
Read-index почти неизбежно отстаёт от основного каталога хотя бы на короткое время. Поэтому интерфейс не должен считать поисковый документ источником окончательной доступности. Поиск находит candidate event или market, а переход на сущность сверяет актуальное состояние уже через продуктовый read path.
Хороший тест: удалить рынок или завершить событие, пока старый документ ещё существует в индексе. Пользователь может увидеть результат поиска, но после открытия должен получить корректный terminal/suspended state, а не 404 или возможность выполнить устаревшее действие. Такой разрыв особенно важен для live-каталога.
Внутренний CQRS read model полезен именно как оптимизированная проекция, а не копия источника истины. Метрики zero-result и stale-hit стоит смотреть отдельно по языкам, спорту и времени до старта — среднее значение часто скрывает локальную проблему.
Доля пустой выдачи в разрезе языка и спорта
Общий процент нулевых запросов скрывает проблему токенизации конкретного языка. Нужны breakdown по locale/sport и отдельный index freshness. Это быстрее приводит к причине, чем ручной просмотр популярных запросов.

Связанные разборы по той же архитектурной цепочке
Нормализация спортивных данных: единая модель событий
Как переводить данные разных поставщиков во внутреннюю модель: исходный пакет, версии, неизвестные значения, сопоставление и диагностические сигналы.
Перейти к разбору →НадёжностьСессия пользователя и публичный кэш: где проходит граница
Как отделить публичную страницу события от данных аккаунта, сохранить эффективность кэша и не допустить персональные данные в общий ответ.
Перейти к разбору →НадёжностьСпортивная платформа под высокой нагрузкой: как проектировать запас прочности
Как меняются очереди, разделение потоков и стратегия деградации, когда число событий и потребителей растёт одновременно.
Перейти к разбору →Букмекерская логикаКнопка коэффициента: доступность, изменение цены и приостановка
Как проектировать кнопку коэффициента: изменение цены, приостановка, фокус, клавиатурное управление и понятные состояния после выбора пользователя.
Перейти к разбору →