Отделим отбор документов от оценки и научимся читать Query DSL как дерево.
Примеры course-products используют учебную схему и товар из главы 5 «Mapping и типы полей». Разборы упражнений ниже используют отдельный публичный набор тренажёра.
- Дерево условий
- Два вопроса к документу
- Постоянная оценка и кеш
Отделим отбор документов от оценки и научимся читать Query DSL как дерево.
Курс ориентирован на Elasticsearch 9.4.3. Разборы упражнений используют публичный набор products; остальные запросы показывают отдельные учебные индексы и могут требовать подготовки или прав, недоступных в тренажёре. Ответы сокращены, score может меняться. Для расширенных функций проверяйте лицензию и вариант развёртывания.
Дерево условий
Leaf query проверяет конкретное условие: term, range или match. Compound query объединяет другие запросы или меняет их оценку: bool, dis_max, constant_score. JSON описывает дерево, а не последовательность инструкций. Порядок элементов filter не задаёт гарантированный порядок выполнения: движок оптимизирует план самостоятельно.
СамопроверкаДва вопроса к документу
Query context спрашивает, насколько хорошо документ подходит, и может вычислять _score. Filter context решает, проходит ли документ обязательное ограничение. Наличие, tenant_id и диапазон цены обычно относятся к ограничениям. Перенос match в filter не меняет его анализатор, но убирает его вклад в ранжирование. Это решение о смысле запроса, а не механическая оптимизация.
СамопроверкаПостоянная оценка и кеш
match_all задаёт все документы, match_none — ни одного. constant_score оборачивает фильтр и выдаёт одинаковый вклад подходящим документам. Filter context делает некоторые результаты пригодными для кеширования, но кеш зависит от частоты использования, сегментов и внутренних политик. Нельзя обещать, что любой filter будет сохранён или что второй запрос обязательно быстрее.
Все документы с точным брендом получают одинаковый вклад в оценку.
{
"query": {
"constant_score": {
"filter": {
"term": {
"brand": "Sony"
}
}
}
}
}Как читать результат
Все документы с точным брендом получают одинаковый вклад в оценку.
Разбор на примере каталога
Запрос «wireless» с ограничением price<100 содержит два разных решения. Совпадение name даёт основания сравнивать релевантность. Цена определяет допустимость покупки в бюджете, но товар за 20 не обязан быть более текстово релевантным, чем товар за 90. Поэтому match ставят в must, range — в filter. Если пользователь выбрал сортировку по цене, это уже отдельный контракт порядка. Перемещение всех условий в must может внести ненужные оценки и затруднить объяснение результатов.
СамопроверкаВсе товары
Корень тела поиска — JSON-объект. query задаёт условия совпадения. match_all с пустым объектом не ограничивает документы и удобен для знакомства с набором данных. size управляет числом возвращаемых документов, а не числом совпадений; sort делает небольшую демонстрацию воспроизводимой. В JSON нужны двойные кавычки, недопустимы комментарии и завершающая запятая.
hits.total.value показывает число совпавших документов; relation: eq означает точный подсчёт. hits.hits содержит возвращённую страницу. _id идентифицирует документ, _source содержит запрошенные исходные поля, _score — оценку релевантности. took измеряется в миллисекундах и меняется между запусками. Фрагменты ниже опускают took, сведения о шардах и индексе: это сокращение для чтения, а не отдельный формат ответа Elasticsearch.
| Поле | Тип | Назначение |
|---|---|---|
| id | integer | Стабильный ID товара и дополнительный ключ сортировки |
| name / description | text | Анализируемый полнотекстовый поиск |
| brand / brand.keyword | text / keyword | Поиск по тексту / точное значение бренда |
| category / status | keyword | Точные значения с учётом регистра |
| price / rating | double / float | Числа; rating может отсутствовать |
| in_stock / created_at | boolean / date | Наличие / дата создания |
Разберём другой сценарий
{
"query": {
"match_all": {}
},
"size": 2,
"_source": [
"name",
"price"
],
"sort": [
{
"id": "asc"
}
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 300,
"relation": "eq"
},
"hits": [
{
"_id": "1",
"_score": null,
"_source": {
"name": "Wireless",
"price": 100
}
},
{
"_id": "2",
"_score": null,
"_source": {
"name": "Reference device",
"price": 100
}
}
]
}
}Как читать результат
Возвращены два документа, но total равен 300. Порядок id задаёт sort, а не релевантность. _source ограничен name и price для читаемости. Управление выдачей подробно рассматривается в четвёртом уроке.
Фильтр без scoring
bool.filter требует выполнения каждого ограничения без добавления вклада в релевантность. Точный бренд, наличие и цена — подходящие примеры: товар не должен становиться релевантнее только из-за наличия. Если поисковых условий нет, bool только с filter обычно возвращает нулевую оценку.
Контекст распространяется на всю вложенную конструкцию. Вложенный bool с двумя фильтрами означает сгруппированное И. Сохраняйте читаемость и не создавайте уровни без необходимости. Elasticsearch может учитывать фильтры для кеширования, но корректность не должна зависеть от попадания в кеш или конкретного порядка исполнения.
| Условие | Обязательно? | Добавляет score в query context? |
|---|---|---|
| must | Да | Да |
| filter | Да | Нет |
| must_not | Не должно совпасть | Нет |
| should | Зависит от minimum_should_match | Да |
Разберём другой сценарий
{
"query": {
"bool": {
"filter": [
{
"term": {
"brand.keyword": "Sony"
}
},
{
"term": {
"in_stock": false
}
},
{
"range": {
"price": {
"lt": 1200
}
}
}
]
}
},
"size": 2,
"_source": [
"name",
"brand",
"price",
"in_stock"
],
"sort": [
{
"id": "asc"
}
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 40,
"relation": "eq"
},
"hits": [
{
"_id": "3",
"_score": null,
"_source": {
"name": "Sony Travel Speaker 3",
"brand": "Sony",
"price": 100,
"in_stock": false
}
},
{
"_id": "15",
"_score": null,
"_source": {
"name": "Sony USB Cable 15",
"brand": "Sony",
"price": 499,
"in_stock": false
}
}
]
}
}Как читать результат
Товары выполняют все три ограничения. Сортировка по id стабилизирует просмотр; нулевой или null-score в таком ответе не означает ошибку.
Релевантность и фильтры
Прикладной поиск часто сочетает match с оценкой в must и ограничения наличия и цены в filter. Все условия обязательны, но только текст влияет на релевантность. Пример ищет gaming среди товаров в наличии дешевле 800.
Перенос текста в filter может сохранить набор совпадений, но убрать ранжирование по тексту. Перенос бизнес-условий в must может добавить вклад в оценку. Сохраняйте различие даже тогда, когда небольшая выборка выглядит одинаково.
Разберём другой сценарий
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "gaming"
}
}
],
"filter": [
{
"term": {
"in_stock": true
}
},
{
"range": {
"price": {
"lt": 800
}
}
}
]
}
},
"size": 2,
"_source": [
"name",
"price",
"in_stock"
]
}Ответ Elasticsearch
{
"hits": {
"total": {
"value": 20,
"relation": "eq"
},
"hits": [
{
"_id": "4",
"_score": 2.3304372,
"_source": {
"name": "Logitech Gaming Keyboard 4",
"price": 199,
"in_stock": true
}
},
{
"_id": "14",
"_score": 2.3304372,
"_source": {
"name": "Samsung Gaming Keyboard 14",
"price": 199,
"in_stock": true
}
}
]
}
}Как читать результат
Найденные товары выполняют оба фильтра, а их взаимный порядок определяется текстовым поиском. total учитывает все допущенные совпадения, а не только небольшую страницу.
Самопроверка
Сначала ответьте самостоятельно, затем раскройте объяснение.
1. Что описывает JSON Query DSL?
Дерево условий и параметров поиска.
2. Исчезает ли анализ текста в filter?
Нет, match всё ещё анализирует текст, но не влияет на score.
3. Где поставить tenant_id?
В обязательное ограничение, обычно bool.filter, установленное сервером.
4. Всегда ли filter кешируется?
Нет, действует политика кеша и ограничения сегментов.
5. Когда полезен constant_score?
Когда достаточно одинакового вклада для всех прошедших условие документов.
Краткая памятка
- Дерево условий и параметров поиска.
- Нет, match всё ещё анализирует текст, но не влияет на score.
- В обязательное ограничение, обычно bool.filter, установленное сервером.
- Нет, действует политика кеша и ограничения сегментов.
- Когда достаточно одинакового вклада для всех прошедших условие документов.
Официальная документация
Готовы применить знания?
Подтвердите прочтение, чтобы сохранить своё место. Чтение и решение заданий учитываются отдельно в этом браузере с помощью гостевой cookie.