Ответ
Поля типа nested
в Elasticsearch позволяют индексировать массивы объектов таким образом, чтобы сохранить внутреннюю связь между полями каждого объекта в массиве.
Проблема, которую решает nested
По умолчанию Elasticsearch "уплощает" массивы объектов. Рассмотрим документ с отзывами:
{
"reviews": [
{ "author": "John", "rating": 5 },
{ "author": "Alice", "rating": 1 }
]
}
При стандартном индексировании (тип object
) данные сохранятся так:
"reviews.author": ["John", "Alice"],
"reviews.rating": [5, 1]
Связь между автором и его оценкой теряется. Из-за этого запрос "найти документы, где автор John
и рейтинг 1
" ошибочно найдет этот документ, так как оба значения присутствуют в соответствующих массивах, хоть и в разных объектах.
Как nested
решает эту проблему
Тип nested
заставляет Elasticsearch индексировать каждый объект в массиве как отдельный, скрытый внутренний документ. Это сохраняет связи.
1. Определение маппинга:
PUT /products
{
"mappings": {
"properties": {
"reviews": {
"type": "nested"
}
}
}
}
2. Поиск по nested
полю:
Для запросов к таким полям используется специальный nested
query. Он ищет совпадения в рамках одного внутреннего документа.
GET /products/_search
{
"query": {
"nested": {
"path": "reviews",
"query": {
"bool": {
"must": [
{ "match": { "reviews.author": "John" }},
{ "range": { "reviews.rating": { "gte": 4 }}}
]
}
}
}
}
}
Этот запрос найдет только те продукты, где есть отзыв от John
с рейтингом 4 или выше. Запрос на author: "John"
и rating: 1
уже не найдет документ из примера выше, что является корректным поведением.
Важно: Использование nested
полей увеличивает размер индекса и немного замедляет запросы, поэтому их следует применять только тогда, когда сохранение связей внутри объектов массива действительно необходимо.