# Фасетный поиск: проблемы и особенности реализации

Фасетный поиск позволяет покупателю ориентироваться в больших каталогах путем последовательного сужения поиска с помощью фильтров-фасетов.

Работает это по принципу продавца-консультанта: он задает наводящие вопросы и приводит клиента в нужный отдел.

Какой цвет? Какой размер? В результате покупатель попадает к товарам, максимально соответствующим его запросам.

В зависимости от технической реализации, трудности могут начаться уже после первого фильтра. Фасет - это конкретная характеристика товара: цвет, размер и многое другое.

Например, покупатель ищет красные ботинки. После запроса API возвращает подходящие товары и доступные для них фильтры:

  • Получены фильтры: Размер: { name: 35, count:19 }, { name: 36, count: 12 }, { name: 37, count: 8 }, Материал: { name: кожа, count: 15 }, { name: резина, count: 4 }
  • Пользователь выбирает: Размер: 35
  • На сервер уходит запрос с выбранным фильтром
  • Сервер находит товары с этим фильтром и возвращает только те фасеты, которые есть у этих товаров
  • Предположим, что из девятнадцати моделей обуви тридцать пятого размера нет ни одной с материалом резина. Теперь наши фильтры выглядят так: Размер: { name: 35, count:19 }, Материал: { name: кожа, count: 15 }
  • Интерфейс перерисовывается и остаются только эти активные фильтры

Такая ситуация возможна, если фильтрация и отрисовка интерфейса реализованы динамически.

То есть после каждого запроса пользователь видит новый набор фильтров из тех, что имеются у постоянно сужающегося перечня товаров.

Такой подход, при всей его простоте реализации и «чистоте» интерфейса, имеет серьезный недостаток.

Актуальный пример

Представьте, что покупатель ищет товар с определёнными характеристиками. Но он применил фильтр по локации и указал, например, Москву.

Конкретно в Москве такого товара нет, но он есть в наличии в других локациях.

Покупатель может счесть, что такого товара у вас нет в принципе, поскольку из-за уменьшения количества фильтров в интерфейсе можно забыть, что поиск был ограничен конкретной локацией.

# Как избежать потери контекста в фасетном поиске

Фиксированная структура фасетов позволяет избежать проблем, описанных выше. Главное условие - сохранить изначальную структуру фасетов и обеспечить её обновление вместе с новыми запросами.

Рассмотрим как это может выглядеть:

  • Получены фильтры: Размер:{ name: 35, count:19 }, { name: 36, count: 12 }, { name: 37, count: 8 }, Материал:{ name: кожа, count: 15 }, { name: резина, count: 4 }
  • Структура фасетов сохраняется на стороне клиента (кэш, Session Storage, менеджер состояния приложения)
  • Пользователь выбирает: Размер: 35
  • На сервер уходит запрос с выбранным фильтром
  • Сервер находит товары с этим фильтром и возвращает только те фасеты, которые есть у этих товаров
  • Клиентская логика не заменяет старые фасеты новыми. Вместо этого обновляется сохраненная копия на основе нового ответа. Например, новая структура фильтров может выглядеть так: Размер: { name: 35, count:19 }, { name: 36, count: 0 }, { name: 37, count: 0 }, Материал: { name: кожа, count: 15 }, { name: резина, count: 0 }. Используется обозначение количества товаров для каждого фасета
  • Интерфейс отображает полный список фасетов с указанием количества найденных совпадений

Главные преимущества такого подхода: сохранение контекста — наглядно видно, какие свойства товара были найдены поиском, а какие нет; предсказуемость — изменения в интерфейсе понятны и логичны.

Ключевые требования для реализации такого подхода:

  1. Сохранение структуры фасетов на стороне клиента.
  2. Сохранённые фасеты должны обновляться при новых запросах, а не заменяться.

Варианты хранения структуры фасетов

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

Другой вариант — Session Storage сохранит данные до закрытия вкладки, но нужно учитывать ограничения объема памяти.

Реализация хранения через менеджер состояния приложения потребует дополнительных ресурсов разработки.

Выбор зависит от ваших потребностей. Но в любом случае фасетный поиск без потери контекста можно реализовать только с условием выполнения названых требований на стороне клиента.