Назад в блог

Три тысячи результатов — тоже сломанный поиск

Нулевые результаты — красный флаг в дашборде. Их сразу видят. О них сразу пишут задачи.

Три тысячи результатов — зелёный флаг. «Поиск работает.»

Именно они убивают конверсию.

Я работал с каталогом на 28 000 SKU. Запрос «куртка мужская» возвращал 1 400 позиций. Фасеты были. Сортировка была. Пагинация была. Конверсия с поиска была ниже, чем с прямого перехода в категорию. Пользователь вводил запрос — и получал не ответ, а задачу. Найди нужное среди полутора тысяч.

Это не работающий поиск. Это каталог с текстовым фильтром.

Три тысячи результатов не значит «поиск работает»

Метрика «нулевых результатов» появилась в индустрии раньше, чем метрика «слишком много результатов». Это понятно — zero-results это явная поломка. Пустой экран. Пользователь ничего не нашёл.

Три тысячи результатов — неявная поломка. Пользователь что-то нашёл. Только не то, зачем пришёл.

В поведенческих данных это выглядит так: пользователь вводит запрос, видит длинный список, кликает по первому экрану, не находит нужное, уходит. CTR первых трёх позиций при релевантной выдаче — 60–70%. CTR при нерелевантной — 20–30%. Остальные 70–80% результатов существуют только как число в дашборде.

Разница в конверсии между «нашёл на первом экране» и «не нашёл» — в среднем 3–5x в пользу первого. Это не теория. Это логи.

Дефолтная сортировка убивает конверсию раньше, чем вы это заметите

Bitrix ORM по умолчанию сортирует товары по дате добавления. Не баг. Просто поведение базы данных при ORDER BY id DESC. Для нового магазина на 200 SKU это незаметно. Для каталога на 28 000 SKU это означает, что пользователь запрашивает «ботинки», получает 640 позиций, и первые 20 — это то, что добавили последним. Последнее добавленное не обязательно самое нужное.

Диагноз простой: откройте свой поиск, введите любой широкий запрос, посмотрите на первые 10 результатов. Если это не самые продаваемые товары по этому запросу — сортировка сломана.

Шаг первый перед любым улучшением scoring: переключить дефолтную сортировку с date_asc/date_desc на что-то осмысленное. Это займёт час. Иногда этого достаточно, чтобы поднять конверсию с поиска на 10–15%.

Что значит «осмысленное»: сортировка по популярности (количество заказов за последние 30 дней), по наличию на складе в первую очередь, по маржинальности если есть такая метрика. Любой из этих критериев лучше хронологии.

Как Elasticsearch scoring работает на реальном каталоге

Elasticsearch по умолчанию использует BM25 — алгоритм, который считает релевантность через частоту слова в документе и его редкость в индексе. Для поиска по текстам это хорошо. Для каталога товаров — не всегда.

BM25 не знает, что товар «в наличии». Не знает, что он продаётся в 10 раз лучше похожих. Не знает, что у него маржа выше. BM25 знает только текст.

Для каталога нужен function_score. Это обёртка поверх BM25, которая позволяет добавить числовые сигналы к текстовому ранжированию.

Пример из реального проекта. Для 28k SKU каталога мы добавили три boost-фактора:

  • stock_quantity > 0 — мультипликатор 1.5. Товар в наличии поднимается выше.
  • orders_30d — field_value_factor, weight 0.3. Популярные товары получают бонус.
  • margin_score — field_value_factor, weight 0.2. Маржинальные товары чуть выше.

До этого: запрос «куртка мужская», 1 400 результатов, в топ-10 попадали новинки без продаж. После: 1 400 результатов осталось, но в топ-10 — бестселлеры в наличии. CTR первого экрана вырос с 28% до 51%.

Result set не уменьшился. Но пользователь нашёл нужное.

Это важное различие: scoring не убирает результаты, он переставляет их. Пользователь видит то же количество, но сначала — то, что ему, скорее всего, нужно.

Pre-selection фасетов: уменьшить result set до запроса пользователя

Scoring поднимает нужное наверх. Но иногда нужно именно уменьшить количество.

Для каталога с широкими категориями (одежда, электроника, товары для дома) 1 000+ результатов — не редкость даже при хорошем ранжировании. В этом случае помогает pre-selection: предварительный выбор одного-двух фасетов на основе сигналов запроса.

Пример: пользователь вводит «ботинки мужские зимние». Сигналы в запросе — пол: мужской, сезон: зима. Если поиск умеет их прочитать, он может автоматически включить фильтр по полу и сезону, не требуя от пользователя клика на фасет.

Словарный мэппинг ключевых слов → значения фасетов. «Мужские» → gender:male. «Зимние» → season:winter. При совпадении фасет включается автоматически, result set уменьшается до 80–200 позиций вместо 640.

По поведенческим данным: автоматический выбор фасета при запросе с явным сигналом повышает добавление в корзину с поиска на 8–14%. Потому что пользователь не тратит время на ручную фильтрацию.

Это не AI и не ML. Это словарь на 50–100 пар. Делается за два дня. Механику изменения порядка фасетов на основе поведенческих данных разбирали отдельно.

Что мы измеряли: как понять, что 200 лучше 2000

Главная ошибка при оценке поиска — смотреть только на «нашёл / не нашёл». Это бинарная метрика, которая скрывает качество.

Смотрели на четыре вещи.

CTR первого экрана: доля кликов на первые 10 результатов. При хорошем ранжировании — 55–65%. Если ниже 35%, scoring нужно трогать.

Time-to-click: сколько секунд от получения результатов до первого клика. Если он растёт при низком CTR — пользователь не понимает, что выбрать, не листает в поисках нужного.

Search-to-add-to-cart: доля сессий с запросом, которые закончились добавлением в корзину. В нашем кейсе 4.1% до изменений, 6.8% после. Это главная цифра.

Abandonment: пользователь ввёл запрос и ушёл без клика. Если растёт вместе с количеством результатов — выбор слишком велик, пользователь просто не берётся.

Про zero-results как отдельный источник продуктовых задач — у нас был отдельный разбор. Это параллельная история.

Итог

Три тысячи результатов — это поиск, который не принял решение. Пользователь приходит за ответом, получает задачу и уходит.

Дефолтная сортировка, scoring, pre-selection по сигналам запроса — каждое из этого меняет картину. Можно начать с самого простого: сменить ORDER BY id DESC на ORDER BY orders_30d DESC. Это час работы.

Остальное — следующий шаг. Elasticsearch как инструмент UX, а не только скорости — там же.