Аналитика запросов
Популярные запросы, low-CTR, reformulations — как их читать, чтобы тюнить relevance.
Таб запросов — то, где большинство команд проводят основное время аналитики. Он отвечает на что ищут и сработали ли результаты, и комбинация этих ответов решает большинство вопросов о качестве поиска.
Что фиксируется по каждому запросу
Каждый публичный поиск (/api/search, /api/search/multi) пишет строку SearchUsageEvent с type: "search_query" и metadata, где:
- Нормализованный запрос (lowercased, обрезанный).
found(кол-во результатов).- Латентность в мс.
- Filter-выражение (если было).
sessionIdи опциональныйanonymousUserIdдля группировки.queryId— server-id, связывающий последующие клики с этим поиском.
Click-события (type: "result_click") несут queryId обратно, чтобы CTR per query считался без джойнов.
Популярные запросы (Top Queries)
Top Queries сортирует запросы по объёму за период:
const top = await orpc.search.topQueries.call({
organizationId,
period: "30d",
limit: 10,
});Возвращает:
Array<{
query: string;
searches: number;
clicks: number;
ctr: number; // clicks / searches
resultsFound: number; // среднее за период
zeroResults: boolean; // true, если средний found = 0
}>Как читать:
- Объём + высокий CTR. Работает. Не тюньте.
- Объём + CTR < ~10%. Кандидаты на relevance — смотрите Relevance tuning.
- Объём + zero results. Gap в контенте — No-results.
- Объём + медленная латентность. Производительность — Operations / Performance.
В дашборде ограничьте топ-10; больше — через API.
Low-CTR-запросы
Тот же срез, но по наименьшему CTR при ≥ N searches (default: 5 searches на период). Это запросы, где есть демонстрированный спрос, но список результатов не убеждает.
const lowCtr = await orpc.search.topQueries.call({
organizationId,
period: "30d",
limit: 50,
minSearches: 5,
orderBy: "ctr_asc",
});Двухшаговый playbook:
- Прогоните запрос в Search Preview. Гляньте топ-10. Если нужного продукта нет — retrieval ломается; правим веса
queryByили добавляем синоним. - Если нужный есть, но не наверху. Pin-curation на этом запросе.
Для high-volume / low-CTR, которые упираются — пересмотрите поверхность: возможно, нужен AI answer или federated multi-search.
Reformulations
Reformulation — пользователь запустил A, посмотрел результаты, тут же запустил B (в том же sessionId, обычно в 30 секундах). Сигнал: A не подошёл, B — настоящий intent.
Дашборд показывает топ пар:
| Original | Reformulation | Sessions |
|---|---|---|
running shoes | nike running shoes | 142 |
tv | oled tv | 89 |
phone case | iphone 15 case | 73 |
Reformulations — бесплатный поиск синонимов. Когда «running shoes» → «nike running shoes» — частая пара, бренд имплицитен в широком запросе; возможно, надо поднять вес brand в queryBy.
Чтобы дёрнуть:
const reform = await orpc.search.analyticsEvents.call({
organizationId,
period: "30d",
type: "search_query",
groupBySession: true,
});
// Постобработка: соседние строки в одной сессии.Чтение по локалям
При мульти-локальном каталоге читайте с группировкой по metadata.locale. Запрос с большим объёмом в одной локали и пустой в другой — это translation/routing-проблема, не relevance.
То же для metadata.indexSlug — дашборд по умолчанию даёт org-wide, но per-index drill-down часто показывает другие паттерны.
Длина и форма запроса
Два распределения, за которыми следить:
- Медианная длина. Тренд в сторону длинных запросов часто значит, что пользователи устали от коротких ключевиков и пробуют предложения. Сигнал — включить Semantic search hybrid.
- Wildcard / browse rate. Запросы с
q: "*"(browse с фильтрами) vs full-text. Перевес*— либо здоровая UX фильтров, либо недоверие к поисковой строке.
Оба извлекаются из сырых event metadata через analyticsEvents.
Сравнение периодов
Дашборд показывает один период. Для period-over-period — два окна и diff на клиенте:
const [a, b] = await Promise.all([
orpc.search.topQueries.call({ organizationId, period: "30d", limit: 200 }),
orpc.search.topQueries.call({ organizationId, period: "30d", offsetDays: 30, limit: 200 }),
]);
// Дельта per query.offsetDays сдвигает окно назад. Удобно ловить drift после деплоя.
Кэш и пагинация topQueries
topQueries использует per-org-кэш с TTL ~5 минут. Дашборд обновляет по кнопке; программные callers пусть кэшируют так же (агрегация по SearchUsageEvent затратна на крупных тенантах).
Пагинация — offset. Для пуллов > 1000 строк — Export.