Data engineering
Полнотекстовый поиск: построй и мигрируй поисковый индекс
Читать про паритет анализаторов и reindex-миграции — не то же самое, что выкатить поисковую фичу, которая переживает фикс бага stemming на масштабе. Построй поиск по реальному корпусу, докажи его релевантность числами, затем проведи миграцию, которая рано или поздно нужна каждой поисковой системе — так, чтобы никто не заметил.
Преврати модель юнита в работающую систему: проиндексируй корпус в inverted index, обеспечь один анализатор при индексировании и при запросе, оттюнь BM25 на judged queries и отрепетируй zero-downtime reindex-за-алиасом, который навязывает движок с неизменяемыми токенами.
Построй full-text search по реальному корпусу документов (≥50k документов) — сначала на Postgres tsvector/GIN, затем опционально на Elasticsearch/OpenSearch — который возвращает релевантные ранжированные результаты за миллисекунды, и докажи это измеренной релевантностью и zero-downtime миграцией анализатора.
- Таблица релевантности: precision@10 (или nDCG@10) до и после тюнинга на том же judged-query наборе, измеренные, а не оценённые, без класса запросов, ухудшенного ниже базы.
- Доказательство защиты паритета анализаторов: прогон намеренного mismatch, возвращающий ноль результатов, и тест паритета, который теперь это предотвращает — оба зафиксированы.
- Вывод EXPLAIN (ANALYZE), доказывающий, что запрос поиска использует GIN-индекс (bitmap/index scan), а не sequential scan по корпусу.
- Лог миграции, показывающий построение и переиндексацию нового индекса, атомарный swap read-алиаса и корректно обслуженные запросы на протяжении всего процесса — с абзацем, почему ограничение неизменяемых токенов форсирует rebuild-and-swap, а не правку на месте.
- Добавь второй бэкенд (Elasticsearch или OpenSearch) по тому же корпусу и сравни релевантность, латентность и операционную стоимость с версией на Postgres на идентичном judged-query наборе.
- Добавь fuzzy/typo-толерантность (pg_trgm в Postgres или fuzziness в ES) и измерь, насколько она улучшает recall на подмножестве запросов с опечатками, не разрушая precision.
- Добавь faceting/aggregations (счётчики по категориям рядом с результатами) и измерь стоимость латентности вычисления facets на запрос.
- Добавь near-real-time обработку записи: принимай поток новых документов, подними refresh_interval (или батчи обновлений tsvector) под bulk-загрузкой и покажи, что пропускная способность записи растёт, задокументировав принятый компромисс по латентности видимости.
Это цикл, который ты прогоняешь, когда поиск — твоя ответственность: индексируй в inverted-структуру, обеспечь один анализатор на обеих сторонах и защити его тестом паритета, тюнь ранжирование на judged queries реальными числами и отрепетируй reindex-за-алиасом миграцию, которую движок с неизменяемыми токенами рано или поздно потребует. Сделав это один раз на реальном корпусе, ты делаешь mismatch анализаторов и reindex-миграции очевидными, а не пугающими, когда они всплывут в production.