Раздел 40 · Elasticsearch и ELK

bool-запросы: must, should, must_not, filter

junior~10 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Настоящий поиск в каталоге «Гонца» это не одно условие. Клиент набрал «пицца», а ещё в приложении включены фильтры: только то, что сейчас в наличии, дешевле 500 рублей, без острого. И хорошо бы выше показать пиццы с грибами, потому что клиент их часто заказывает. Собрать такие условия в один запрос помогает bool.

Четыре корзины условий

bool раскладывает условия по четырём корзинам:

КорзинаДокумент обязан подходить?Влияет на _score?
mustдада
filterданет
must_notобязан не подходитьнет
shouldнет, если есть must или filterда, совпадение поднимает выше
{
  "query": {
    "bool": {
      "must":     [ { "match": { "name": "пицца" } } ],
      "filter":   [ { "term": { "available": true } },
                    { "range": { "price_rub": { "lte": 500 } } } ],
      "must_not": [ { "term": { "tags": "spicy" } } ],
      "should":   [ { "match": { "description": "грибы" } } ]
    }
  }
}

В каждой корзине массив запросов, и их можно вкладывать: внутри should может стоять ещё один bool.

Запрос и фильтр

Самое важное различие здесь между must и filter. У Elasticsearch два режима условий:

  • контекст запроса: насколько хорошо документ подходит? Здесь считается _score. Это must и should;
  • контекст фильтра: подходит или нет? Только да или нет, без оценки. Это filter и must_not.

Цена дешевле 500 рублей либо выполняется, либо нет: «насколько хорошо» тут не бывает. Если положить такое условие в must, оно всё равно будет участвовать в подсчёте оценки и чуть-чуть сдвигать порядок без всякого смысла. А в filter оно просто отсекает лишнее. Есть и второй выигрыш: Elasticsearch кэширует результаты частых фильтров, и повторный запрос с теми же фильтрами идёт быстрее.

Правило простое: всё, что про точное совпадение (кухня, наличие, цена, дата, тег), идёт в filter. Всё, что про слова и «насколько подходит», в must и should.

урок из курса

Урок из курса «Elasticsearch и ELK». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.