bool-запросы: must, should, must_not, filter
Учимся собирать сложные запросы из простых условий через bool — главный конструктор запросов Elasticsearch.
bool-запрос комбинирует несколько условий через четыре секции:
must,should,must_notиfilter.
Зачем
Реальный поиск редко состоит из одного условия. «Ноутбуки бренда Lenovo, дешевле 80000, в наличии, желательно с SSD» — это пять условий разной природы. bool позволяет собрать их в один запрос, как AND/OR/NOT в SQL, но с учётом релевантности.
Четыре секции
| Секция | Смысл | Влияет на score? |
must | обязано совпасть (логическое И) | да |
should | желательно совпасть (повышает score) | да |
must_not | не должно совпасть (логическое НЕ) | нет (только исключает) |
filter | обязано совпасть, но без подсчёта релевантности | нет (только фильтрует) |
Пример
{
"query": {
"bool": {
"must": [ { "match": { "title": "ноутбук lenovo" } } ],
"should": [ { "match": { "description": "ssd" } } ],
"must_not": [ { "term": { "status": "discontinued" } } ],
"filter": [
{ "term": { "in_stock": true } },
{ "range": { "price": { "lt": 80000 } } }
]
}
}
}Читается так: документ обязан подходить под «ноутбук lenovo»; если в описании есть «ssd» — поднимется в выдаче; не должен быть со статусом discontinued; обязан быть в наличии и дешевле 80000 — но эти два условия только отсеивают, не влияя на ранжирование.
filter против must — важнейшее различие
И must, и filter делают условие обязательным. Разница в двух вещах:
- Релевантность.
mustучаствует в подсчёте_score,filter— нет (для него важно только «да/нет»). - Кеширование. Результаты
filterкешируются и переиспользуются между запросами. Поэтому точные условия («в наличии», «цена в диапазоне», «дата за месяц») лучше класть вfilter— это и быстрее, и логически правильнее.
Как работает под капотом
ES вычисляет каждую секцию как набор подходящих документов (постинг-листы) и комбинирует их: must и filter пересекаются, must_not вычитается, should добавляет очки совпавшим. Для filter движок не считает TF-IDF/BM25 — он только проверяет принадлежность, поэтому может закешировать результат как битовую маску документов и мгновенно переиспользовать на следующих запросах. Это делает фильтры очень дешёвыми.
Частые ошибки
- Класть точные фильтры в must. «Цена < 80000» и «в наличии» не нужны для релевантности — в
filterони быстрее и кешируются. - Думать, что should обязателен. Если в bool есть
mustилиfilter,shouldпо умолчанию необязателен и лишь повышает score. Поведением управляет параметрminimum_should_match.
Итоги
boolсобирает запрос из секций:must(И),should(буст),must_not(НЕ),filter(И без score).filterне влияет на релевантность и кешируется — туда кладут точные условия.mustиshouldучаствуют в ранжировании,must_notиfilter— только отбирают документы.