Разное → Хитро-зависимые значения фасетов в Solr

24.10.2022

Имеется три фасета:

Категория              Бренд                Наличие
[ ] Процессоры (37)    [ ] AMD (12)         [ ] В наличии (10)
[ ] Охлаждение (33)    [ ] Intel (25)       [ ] Под заказ (40)
                       [ ] Zalman (15)
                       [ ] DeepCool (18)

Фасеты получаются стандартным способом:

q=*:*&
facet=true&
facet.field={!ex=category}s_category&
facet.field={!ex=brand}s_brand&
facet.field={!ex=stock}s_stock

Задача — сделать так, чтобы список значений в фасетах "Бренд" и "Наличие" зависели от выбранной категории, но при этом не зависели друг от друга:

Категория              Бренд             Наличие
[x] Процессоры (37)    [ ] AMD (12)      [ ] В наличии (5)
[ ] Охлаждение (33)    [ ] Intel (25)    [ ] Под заказ (30)
Категория              Бренд             Наличие
[x] Процессоры (5)     [ ] AMD (5)       [x] В наличии (5)
[ ] Охлаждение (4)     [ ] Intel (0)     [ ] Под заказ (30)

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

Проблема в том, что при facet.mincount=0 Solr выведет все значения, которые есть в индексе:

Категория              Бренд             Наличие
[x] Процессоры (37)    [ ] AMD (12)      [ ] В наличии (5)
[ ] Охлаждение (33)    [ ] Intel (25)    [ ] Под заказ (30)
                       [ ] Zalman (0)
                       [ ] DeepCool (0)
Категория              Бренд             Наличие
[x] Процессоры (5)     [ ] AMD (5)       [x] В наличии (5)
[ ] Охлаждение (4)     [ ] Intel (0)     [ ] Под заказ (30)
                       [ ] Zalman (0)
                       [ ] DeepCool (0)

А при facet.mincount=1 выведет только те, у которых счётчик больше нуля:

Категория              Бренд             Наличие
[x] Процессоры (37)    [ ] AMD (12)      [ ] В наличии (5)
[ ] Охлаждение (33)    [ ] Intel (25)    [ ] Под заказ (30)
Категория              Бренд             Наличие
[x] Процессоры (5)     [ ] AMD (5)       [x] В наличии (5)
[ ] Охлаждение (4)                       [ ] Под заказ (30)

Решения на чистом Solr я так и не нашёл, но наткнулся на костыль, суть которого в том, чтобы на каждый фасет, который зависит от "глобального" (в нашем случае от категории) добавить по новому facet.field, в котором с помощью local parameters исключить "не глобальные" фильтры, а затем уже на бэке (PHP) объединить результаты.

Пример запроса с выбранной категорией и наличием:

q=*:*&
fq={!tag=category}s_category:Процессоры&
fq={!tag=stock}s_stock:"В наличии"
facet=true&
facet.mincount=1&
facet.field={!ex=category}s_category&
facet.field={!ex=brand}s_brand&
facet.field={!ex=stock}s_stock&
facet.field={!ex=brand,stock key=s_brand_ex}s_brand&
facet.field={!ex=brand,stock key=s_stock_ex}s_stock

Ответ:

"s_category": {
  "Процессоры", 5,
  "Охлаждение", 4
},
"s_brand": {
  "AMD", 5
},
"s_stock": {
  "В наличии", 5,
  "Под заказ", 30
},
"s_brand_ex": {
  "AMD", 12,
  "Intel", 25
},
"s_stock_ex": {
  "В наличии", 5,
  "Под заказ", 30
}

В s_brand и s_stock будет список зависимый от всех фильтров, а в s_brand_ex и s_stock_ex только от категории. Соответственно уже на PHP к s_brand и s_stock добавляем значения из s_brand_ex/s_stock_ex и заполняем их нолями.

Написанное актуально для
Solr 8.11

Добавить комментарий