Переведём бизнес-правила в дерево bool и разберём неочевидное поведение should.
Примеры course-products используют учебную схему и товар из главы 5 «Mapping и типы полей». Разборы упражнений ниже используют отдельный публичный набор тренажёра.
- Обязательные ограничения
- Группа альтернатив
- Совпадение + score
Переведём бизнес-правила в дерево bool и разберём неочевидное поведение should.
Курс ориентирован на Elasticsearch 9.4.3. Разборы упражнений используют публичный набор products; остальные запросы показывают отдельные учебные индексы и могут требовать подготовки или прав, недоступных в тренажёре. Ответы сокращены, score может меняться. Для расширенных функций проверяйте лицензию и вариант развёртывания.
Четыре роли условий
must требует совпадения и может влиять на score; filter требует совпадения без вклада в score; must_not исключает. should задаёт альтернативы или бонусы. Условия одного must или filter объединяются через AND. Массив should — не универсальный обязательный OR: его обязательность зависит от остальных частей bool и minimum_should_match.
СамопроверкаНеявные значения
Если bool содержит should и не содержит must или filter, по умолчанию нужен один should. При наличии must или filter значение по умолчанию становится нулём. Добавив фильтр наличия, можно случайно превратить обязательный набор брендов в необязательные бонусы. Если альтернативы обязательны по бизнес-смыслу, указывайте minimum_should_match явно или помещайте их в отдельный вложенный bool.
СамопроверкаСкобки и отрицание
Условие «в наличии И (бренд A ИЛИ цена ниже 100)» требует вложенной группы. Исключение товара и исключение отдельного nested-предложения — разные задачи. Для сложных правил сначала выпишите таблицу примеров: какие товары обязаны пройти и какие не должны. Имена запросов помогают диагностировать совпавшие ветви, но могут добавлять стоимость.
Явное требование одной альтернативы сохраняет смысл при добавлении фильтров.
{
"query": {
"bool": {
"filter": [
{
"term": {
"in_stock": true
}
}
],
"should": [
{
"term": {
"brand": "Sony"
}
},
{
"range": {
"price": {
"lt": 100
}
}
}
],
"minimum_should_match": 1
}
}
}Как читать результат
Явное требование одной альтернативы сохраняет смысл при добавлении фильтров.
Разбор на примере каталога
Для условия in_stock AND (Sony OR price<100) составьте четыре товара: Sony/150/в наличии, Bose/50/в наличии, Bose/150/в наличии, Sony/50/нет в наличии. Первые два проходят, последние два — нет. Если после добавления filter проходит третий товар, альтернативы стали необязательными. Если проходит четвёртый, потерялось обязательное ограничение наличия. Такая таблица фиксирует бизнес-смысл и остаётся полезной даже при полном изменении формы JSON.
СамопроверкаОбязательные условия
Каждое условие bool.must обязано совпасть. В query context эти условия также участвуют в оценке. Список из match и term одновременно требует текстового совпадения и точного условия. Пример ищет gaming в name и требует наличие: это И, а не выбор между словом и логическим значением.
Одиночное условие можно записать объектом, несколько обычно записывают массивом. Выбирайте понятный единый стиль. В прикладном поиске наличие чаще удобно вынести в filter, но этот раздел отдельно показывает must: упражнение может намеренно требовать конкретный контекст.
Разберём другой сценарий
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "gaming"
}
},
{
"term": {
"in_stock": true
}
}
]
}
},
"size": 2,
"_source": [
"name",
"in_stock"
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 20,
"relation": "eq"
},
"hits": [
{
"_id": "4",
"_score": 2.7367332,
"_source": {
"name": "Logitech Gaming Keyboard 4",
"in_stock": true
}
},
{
"_id": "14",
"_score": 2.7367332,
"_source": {
"name": "Samsung Gaming Keyboard 14",
"in_stock": true
}
}
]
}
}Как читать результат
Каждый товар подходит по тексту и находится в наличии. Оценка определяется поисковыми условиями, а не количеством полей JSON.
Исключение товаров
Условие must_not исключает документ, если внутренний запрос совпал. При нескольких must_not ни одно из них не должно совпасть: исключение статуса A и статуса B убирает обе группы. Это не требование отличаться только от одного значения.
bool только с must_not начинает со всех документов и вычитает совпадения. Поэтому отсутствующие значения могут остаться: документ без status не совпадает с term status: preorder и этим условием не исключается. Если нужно наличие поля, добавьте exists как отдельное обязательное условие.
Разберём другой сценарий
{
"query": {
"bool": {
"must_not": [
{
"term": {
"status": "preorder"
}
}
]
}
},
"size": 2,
"_source": [
"name",
"status"
],
"sort": [
{
"id": "asc"
}
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 200,
"relation": "eq"
},
"hits": [
{
"_id": "2",
"_score": null,
"_source": {
"name": "Reference device",
"status": "discontinued"
}
},
{
"_id": "3",
"_score": null,
"_source": {
"name": "Sony Travel Speaker 3",
"status": "active"
}
}
]
}
}Как читать результат
Ни один возвращённый товар не имеет preorder. Запрос намеренно оставляет active и discontinued: он показывает исключение, а не полную политику доступности.
Альтернативные бренды
should задаёт альтернативы. В примере это категории, а не бренды: достаточно Audio или Accessories. minimum_should_match: 1 явно фиксирует ИЛИ, хотя bool только с should и так по умолчанию требует одно совпадение. Явное значение особенно важно при добавлении обязательных условий.
Каждая альтернатива может быть целым деревом запроса. Для (A И B) ИЛИ (C И D) поместите в should две вложенные bool-группы, а не четыре независимых условия. В финальном уроке такое группирование связывает категории с разными диапазонами цен.
| A | B | A И B | A ИЛИ B |
|---|---|---|---|
| ложь | ложь | ложь | ложь |
| ложь | истина | ложь | истина |
| истина | ложь | ложь | истина |
| истина | истина | истина | истина |
Разберём другой сценарий
{
"query": {
"bool": {
"should": [
{
"term": {
"category": "Audio"
}
},
{
"term": {
"category": "Accessories"
}
}
],
"minimum_should_match": 1
}
},
"size": 2,
"_source": [
"name",
"category"
],
"sort": [
{
"id": "asc"
}
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 150,
"relation": "eq"
},
"hits": [
{
"_id": "2",
"_score": null,
"_source": {
"name": "Reference device",
"category": "Audio"
}
},
{
"_id": "4",
"_score": null,
"_source": {
"name": "Logitech Gaming Keyboard 4",
"category": "Accessories"
}
}
]
}
}Как читать результат
Каждый товар относится хотя бы к одной разрешённой категории. Обе одновременно не требуются, что важно для нашего однозначного category.
Минимум совпадений
minimum_should_match задаётся в том bool, чьими should он управляет. При наличии must или filter значение по умолчанию равно нулю; без них — единице. Для «не меньше двух признаков» задайте число явно. Пример требует два из трёх слов в name и одновременно ограничивает наличие.
Подсчитываются совпавшие условия should, а не число терминов одного match. Один match с несколькими словами всё ещё является одним should-условием. Для отдельно учитываемых признаков нужны отдельные конструкции; внутри каждой match анализатор продолжает обрабатывать регистр и токены.
Разберём другой сценарий
{
"query": {
"bool": {
"filter": [
{
"term": {
"in_stock": true
}
}
],
"should": [
{
"match": {
"name": "wireless"
}
},
{
"match": {
"name": "premium"
}
},
{
"match": {
"name": "mouse"
}
}
],
"minimum_should_match": 2
}
},
"size": 2,
"_source": [
"name",
"in_stock"
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 39,
"relation": "eq"
},
"hits": [
{
"_id": "7",
"_score": 3.2707968,
"_source": {
"name": "Apple Wireless Mouse 7",
"in_stock": true
}
},
{
"_id": "17",
"_score": 3.2707968,
"_source": {
"name": "Dell Wireless Mouse 17",
"in_stock": true
}
}
]
}
}Как читать результат
Подходящее название содержит как минимум два запрошенных словесных признака. Одного совпадения по наличию недостаточно.
Сложные бизнес-условия
Начните с формулы S И (A ИЛИ B). S — общий допуск: наличие и разрешённые статусы. Каждая ветвь связывает свою категорию со своим диапазоном. В примере S разрешает только preorder, A — Accessories дешевле 200, B — Smartphones от 200 включительно до 900 исключительно.
Разместите общие ограничения во внешнем filter, две ветви во внешнем should и minimum_should_match: 1 на том же уровне. Внутри ветви используйте bool.filter для категории И цены. Плоский should из четырёх отдельных условий пропускает, например, дешёвый товар чужой категории.
Проверьте нижнюю границу, верхнюю, документ только с нужной категорией, документ только с подходящей ценой и отсутствующий на складе товар, полностью подходящий ветви. Такие случаи отличают правильную группировку от случайно широкого запроса. В практическом задании примените ту же логику к другим значениям.
| Общее S | Ветвь A | Ветвь B | Принять? |
|---|---|---|---|
| ложь | истина | истина | Нет |
| истина | ложь | ложь | Нет |
| истина | истина | ложь | Да |
| истина | ложь | истина | Да |
Разберём другой сценарий
{
"query": {
"bool": {
"filter": [
{
"term": {
"in_stock": true
}
},
{
"term": {
"status": "preorder"
}
}
],
"should": [
{
"bool": {
"filter": [
{
"term": {
"category": "Accessories"
}
},
{
"range": {
"price": {
"lt": 200
}
}
}
]
}
},
{
"bool": {
"filter": [
{
"term": {
"category": "Smartphones"
}
},
{
"range": {
"price": {
"gte": 200,
"lt": 900
}
}
}
]
}
}
],
"minimum_should_match": 1
}
},
"size": 2,
"_source": [
"name",
"category",
"price",
"status",
"in_stock"
],
"sort": [
{
"id": "asc"
}
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 15,
"relation": "eq"
},
"hits": [
{
"_id": "4",
"_score": null,
"_source": {
"name": "Logitech Gaming Keyboard 4",
"category": "Accessories",
"price": 199,
"in_stock": true,
"status": "preorder"
}
},
{
"_id": "25",
"_score": null,
"_source": {
"name": "Apple USB Cable 25",
"category": "Smartphones",
"price": 499,
"in_stock": true,
"status": "preorder"
}
}
]
}
}Как читать результат
Каждый товар проходит общие ограничения и целую ветвь категория–цена. Условие из ветви A нельзя соединить с несвязанным условием из B.
Самопроверка
Сначала ответьте самостоятельно, затем раскройте объяснение.
1. Когда should по умолчанию обязателен?
Если есть should и нет must или filter, требуется одно совпадение.
2. Что меняется после добавления filter?
Неявный minimum_should_match становится нулём.
3. Чем must отличается от filter?
Оба требуют совпадения, но filter не вносит score.
4. Как выразить скобки?
Вложенным bool с нужной обязательностью альтернатив.
5. Как проверить бизнес-правило?
Составить положительные и отрицательные примеры, особенно на границах условий.
Краткая памятка
- Если есть should и нет must или filter, требуется одно совпадение.
- Неявный minimum_should_match становится нулём.
- Оба требуют совпадения, но filter не вносит score.
- Вложенным bool с нужной обязательностью альтернатив.
- Составить положительные и отрицательные примеры, особенно на границах условий.
Официальная документация
Готовы применить знания?
Подтвердите прочтение, чтобы сохранить своё место. Чтение и решение заданий учитываются отдельно в этом браузере с помощью гостевой cookie.