Как создать простой фильтр с фасетом?

Привет всем! Можете подсказать, как реализовать фильтр (фасет) в Elasticsearch, аналогичный умному фильтру в битрикс? Например, у нас есть два цвета: красный и желтый, а также размеры: S, M, L, XL. Когда выбирается цвет КРАСНЫЙ, желтый по-прежнему остается доступным, но размеры фильтруются. Если выбрать только размер XL, остальные размеры не исчезают, так как могут быть разные размеры, но цвет фильтруется в агрегации. В моих предыдущих попытках, когда я выбираю цвет красный, в агрегации остается только он. Не подскажете, где в документации Elasticsearch можно найти информацию по этой теме, или не могли бы вы привести пример?
  • 16 февраля 2025 г. 17:04
Ответы на вопрос 2
В Elasticsearch для реализации фасетного фильтра (или умного фильтра) можно использовать агрегации и bool-запросы. Таким образом, можно создать систему фильтрации, которая позволяет пользователю выбирать параметры так, чтобы они не исключали другие варианты.

Вот простой пример того, как это можно реализовать.

### Основная структура документа

Предположим, у нас есть индекс с товарами, и каждый товар имеет два поля: цвет и размер. Пример документа может выглядеть так:

```json
{
  "name": "Футболка",
  "color": "красный",
  "size": "M"
}
```

### Запрос для поиска с фильтрами

Вы можете использовать `bool` запрос с фильтрацией и агрегациями для получения доступных опций к фильтрам. 

Например, чтобы получить все документы с выбранным цветом и размером, можно использовать следующий запрос:

```json
GET /products/_search
{
  "size": 0, 
  "query": {
    "bool": {
      "filter": [
        { "term": { "color": "красный" } },
        { "term": { "size": "XL" } }
      ]
    }
  },
  "aggs": {
    "colors": {
      "terms": {
        "field": "color"
      }
    },
    "sizes": {
      "terms": {
        "field": "size"
      }
    }
  }
}
```

### Ожидаемый результат

В этом запросе:
- Мы фильтруем документы по цвету ("красный") и размеру ("XL").
- В агрегации `colors` мы получаем все доступные цвета, а в агрегации `sizes` — все доступные размеры.

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

### Модификация фильтра

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

### Документация

Более подробную информацию о фильтрациях и агрегациях в Elasticsearch можно найти в следующей документации:

- [Фильтры в запросах](
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html)
- [Агрегации](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html)

Используя эти концепции, вы можете создать сложные фасеты и фильтры, которые обеспечивают пользователю подобный интерфейс, как в "умном фильтре" в Bitrix.
Можно делать 2 запроса в эластик - базовая агрегация без фильтра (все возможные значения) и второй запрос с примененным фильтром. 
1. Получили 2 набора свойств - полный набор и ограниченный по фильтру.
2. Отрисовали фильтр на фронте согласно полному набору свойств.
3. Для свойств, которые не выбраны в фильтре (и только для них) "задизейблили" те значения, для которых агрегация с фильтром выдала 0 штук.

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