Запрос nested
Оборачивает другой запрос для поиска полей nested.
Запрос nested ищет объекты вложенного поля как будто они индексированы как отдельные документы. Если объект соответствует поиску, запрос nested возвращает родительский документ корня.
Пример запроса
Настройка индекса
Для использования запроса nested ваш индекс должен включать отображение поля nested. Например:
resp = client.indices.create(
index="my-index-000001",
mappings={
"properties": {
"obj1": {
"type": "nested"
}
}
},
)
print(resp) response = client.indices.create(
index: 'my-index-000001',
body: {
mappings: {
properties: {
"obj1": {
type: 'nested'
}
}
}
}
)
puts response res, err := es.Indices.Create(
"my-index-000001",
es.Indices.Create.WithBody(strings.NewReader(`{
"mappings": {
"properties": {
"obj1": {
"type": "nested"
}
}
}
}`)),
)
fmt.Println(res, err) const response = await client.indices.create({
index: "my-index-000001",
mappings: {
properties: {
obj1: {
type: "nested",
},
},
},
});
console.log(response); PUT /my-index-000001
{
"mappings": {
"properties": {
"obj1": {
"type": "nested"
}
}
}
} Пример запроса
resp = client.search(
index="my-index-000001",
query={
"nested": {
"path": "obj1",
"query": {
"bool": {
"must": [
{
"match": {
"obj1.name": "blue"
}
},
{
"range": {
"obj1.count": {
"gt": 5
}
}
}
]
}
},
"score_mode": "avg"
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
query: {
nested: {
path: 'obj1',
query: {
bool: {
must: [
{
match: {
"obj1.name": 'blue'
}
},
{
range: {
"obj1.count": {
gt: 5
}
}
}
]
}
},
score_mode: 'avg'
}
}
}
)
puts response res, err := es.Search(
es.Search.WithIndex("my-index-000001"),
es.Search.WithBody(strings.NewReader(`{
"query": {
"nested": {
"path": "obj1",
"query": {
"bool": {
"must": [
{
"match": {
"obj1.name": "blue"
}
},
{
"range": {
"obj1.count": {
"gt": 5
}
}
}
]
}
},
"score_mode": "avg"
}
}
}`)),
es.Search.WithPretty(),
)
fmt.Println(res, err) const response = await client.search({
index: "my-index-000001",
query: {
nested: {
path: "obj1",
query: {
bool: {
must: [
{
match: {
"obj1.name": "blue",
},
},
{
range: {
"obj1.count": {
gt: 5,
},
},
},
],
},
},
score_mode: "avg",
},
},
});
console.log(response); GET /my-index-000001/_search
{
"query": {
"nested": {
"path": "obj1",
"query": {
"bool": {
"must": [
{ "match": { "obj1.name": "blue" } },
{ "range": { "obj1.count": { "gt": 5 } } }
]
}
},
"score_mode": "avg"
}
}
} Параметры верхнего уровня для запроса nested
-
path - (Обязательно, строка) Путь к вложенному объекту, который вы хотите искать.
-
query -
(Обязательно, объект запроса) Запрос, который вы хотите выполнить для вложенных объектов в
path. Если объект соответствует поиску, запросnestedвозвращает родительский документ корня.Вы можете искать вложенные поля с помощью нотации точек, которая включает полный путь, например
obj1.name.Многоуровневая вложенность автоматически поддерживается и обнаруживается, что приводит к внутреннему запросу nested для автоматического соответствия необходимому уровню вложенности, а не корневому, если он существует в другом вложенном запросе.
См. Многоуровневые запросы nested для примера.
-
score_mode -
(Необязательно, строка) Указывает, как баллы соответствия дочерних объектов влияют на релевантность корневого родительского документа. Допустимые значения:
-
avg(По умолчанию) - Используется средний балл релевантности всех соответствующих дочерних объектов.
-
max - Используется наивысший балл релевантности всех соответствующих дочерних объектов.
-
min - Используется наименьший балл релевантности всех соответствующих дочерних объектов.
-
none - Баллы релевантности соответствующих дочерних объектов не используются. Запрос присваивает родительским документам балл
0. -
sum - Складываются баллы релевантности всех соответствующих дочерних объектов.
-
-
ignore_unmapped -
(Необязательно, Булево) Указывает, игнорировать ли неотображенное поле
pathи не возвращать документы вместо ошибки. По умолчаниюfalse.Если
false, Elasticsearch возвращает ошибку, если полеpathне отображено.Вы можете использовать этот параметр для запроса к нескольким индексам, которые могут не содержать поля
path.
Примечания
Контекст запросов сценариев
Если вы выполняете запрос сценария script внутри вложенного запроса, вы можете получить доступ только к значениям документов из вложенного документа, а не из родительского или корневого документа.
Многоуровневые запросы nested
Чтобы увидеть, как работают многоуровневые запросы nested, сначала вам нужен индекс с вложенными полями. Следующий запрос определяет отображения для индекса drivers с вложенными полями make и model.
resp = client.indices.create(
index="drivers",
mappings={
"properties": {
"driver": {
"type": "nested",
"properties": {
"last_name": {
"type": "text"
},
"vehicle": {
"type": "nested",
"properties": {
"make": {
"type": "text"
},
"model": {
"type": "text"
}
}
}
}
}
}
},
)
print(resp) response = client.indices.create(
index: 'drivers',
body: {
mappings: {
properties: {
driver: {
type: 'nested',
properties: {
last_name: {
type: 'text'
},
vehicle: {
type: 'nested',
properties: {
make: {
type: 'text'
},
model: {
type: 'text'
}
}
}
}
}
}
}
}
)
puts response res, err := es.Indices.Create(
"drivers",
es.Indices.Create.WithBody(strings.NewReader(`{
"mappings": {
"properties": {
"driver": {
"type": "nested",
"properties": {
"last_name": {
"type": "text"
},
"vehicle": {
"type": "nested",
"properties": {
"make": {
"type": "text"
},
"model": {
"type": "text"
}
}
}
}
}
}
}
}`)),
)
fmt.Println(res, err) const response = await client.indices.create({
index: "drivers",
mappings: {
properties: {
driver: {
type: "nested",
properties: {
last_name: {
type: "text",
},
vehicle: {
type: "nested",
properties: {
make: {
type: "text",
},
model: {
type: "text",
},
},
},
},
},
},
},
});
console.log(response); PUT /drivers
{
"mappings": {
"properties": {
"driver": {
"type": "nested",
"properties": {
"last_name": {
"type": "text"
},
"vehicle": {
"type": "nested",
"properties": {
"make": {
"type": "text"
},
"model": {
"type": "text"
}
}
}
}
}
}
}
} Затем добавьте некоторые документы в индекс drivers.
$params = [
'index' => 'drivers',
'id' => '1',
'body' => [
'driver' => [
'last_name' => 'McQueen',
'vehicle' => [
[
'make' => 'Powell Motors',
'model' => 'Canyonero',
],
[
'make' => 'Miller-Meteor',
'model' => 'Ecto-1',
],
],
],
],
];
$response = $client->index($params);
$params = [
'index' => 'drivers',
'id' => '2',
'body' => [
'driver' => [
'last_name' => 'Hudson',
'vehicle' => [
[
'make' => 'Mifune',
'model' => 'Mach Five',
],
[
'make' => 'Miller-Meteor',
'model' => 'Ecto-1',
],
],
],
],
];
$response = $client->index($params); resp = client.index(
index="drivers",
id="1",
document={
"driver": {
"last_name": "McQueen",
"vehicle": [
{
"make": "Powell Motors",
"model": "Canyonero"
},
{
"make": "Miller-Meteor",
"model": "Ecto-1"
}
]
}
},
)
print(resp)
resp1 = client.index(
index="drivers",
id="2",
refresh=True,
document={
"driver": {
"last_name": "Hudson",
"vehicle": [
{
"make": "Mifune",
"model": "Mach Five"
},
{
"make": "Miller-Meteor",
"model": "Ecto-1"
}
]
}
},
)
print(resp1) response = client.index(
index: 'drivers',
id: 1,
body: {
driver: {
last_name: 'McQueen',
vehicle: [
{
make: 'Powell Motors',
model: 'Canyonero'
},
{
make: 'Miller-Meteor',
model: 'Ecto-1'
}
]
}
}
)
puts response
response = client.index(
index: 'drivers',
id: 2,
refresh: true,
body: {
driver: {
last_name: 'Hudson',
vehicle: [
{
make: 'Mifune',
model: 'Mach Five'
},
{
make: 'Miller-Meteor',
model: 'Ecto-1'
}
]
}
}
)
puts response {
res, err := es.Index(
"drivers",
strings.NewReader(`{
"driver": {
"last_name": "McQueen",
"vehicle": [
{
"make": "Powell Motors",
"model": "Canyonero"
},
{
"make": "Miller-Meteor",
"model": "Ecto-1"
}
]
}
}`),
es.Index.WithDocumentID("1"),
es.Index.WithPretty(),
)
fmt.Println(res, err)
}
{
res, err := es.Index(
"drivers",
strings.NewReader(`{
"driver": {
"last_name": "Hudson",
"vehicle": [
{
"make": "Mifune",
"model": "Mach Five"
},
{
"make": "Miller-Meteor",
"model": "Ecto-1"
}
]
}
}`),
es.Index.WithDocumentID("2"),
es.Index.WithRefresh("true"),
es.Index.WithPretty(),
)
fmt.Println(res, err)
} const response = await client.index({
index: "drivers",
id: 1,
document: {
driver: {
last_name: "McQueen",
vehicle: [
{
make: "Powell Motors",
model: "Canyonero",
},
{
make: "Miller-Meteor",
model: "Ecto-1",
},
],
},
},
});
console.log(response);
const response1 = await client.index({
index: "drivers",
id: 2,
refresh: "true",
document: {
driver: {
last_name: "Hudson",
vehicle: [
{
make: "Mifune",
model: "Mach Five",
},
{
make: "Miller-Meteor",
model: "Ecto-1",
},
],
},
},
});
console.log(response1); PUT /drivers/_doc/1
{
"driver" : {
"last_name" : "McQueen",
"vehicle" : [
{
"make" : "Powell Motors",
"model" : "Canyonero"
},
{
"make" : "Miller-Meteor",
"model" : "Ecto-1"
}
]
}
}
PUT /drivers/_doc/2?refresh
{
"driver" : {
"last_name" : "Hudson",
"vehicle" : [
{
"make" : "Mifune",
"model" : "Mach Five"
},
{
"make" : "Miller-Meteor",
"model" : "Ecto-1"
}
]
}
} Теперь вы можете использовать многоуровневый запрос nested для соответствия документам на основе полей make и model.
resp = client.search(
index="drivers",
query={
"nested": {
"path": "driver",
"query": {
"nested": {
"path": "driver.vehicle",
"query": {
"bool": {
"must": [
{
"match": {
"driver.vehicle.make": "Powell Motors"
}
},
{
"match": {
"driver.vehicle.model": "Canyonero"
}
}
]
}
}
}
}
}
},
)
print(resp) response = client.search(
index: 'drivers',
body: {
query: {
nested: {
path: 'driver',
query: {
nested: {
path: 'driver.vehicle',
query: {
bool: {
must: [
{
match: {
'driver.vehicle.make' => 'Powell Motors'
}
},
{
match: {
'driver.vehicle.model' => 'Canyonero'
}
}
]
}
}
}
}
}
}
}
)
puts response res, err := es.Search(
es.Search.WithIndex("drivers"),
es.Search.WithBody(strings.NewReader(`{
"query": {
"nested": {
"path": "driver",
"query": {
"nested": {
"path": "driver.vehicle",
"query": {
"bool": {
"must": [
{
"match": {
"driver.vehicle.make": "Powell Motors"
}
},
{
"match": {
"driver.vehicle.model": "Canyonero"
}
}
]
}
}
}
}
}
}
}`)),
es.Search.WithPretty(),
)
fmt.Println(res, err) const response = await client.search({
index: "drivers",
query: {
nested: {
path: "driver",
query: {
nested: {
path: "driver.vehicle",
query: {
bool: {
must: [
{
match: {
"driver.vehicle.make": "Powell Motors",
},
},
{
match: {
"driver.vehicle.model": "Canyonero",
},
},
],
},
},
},
},
},
},
});
console.log(response); GET /drivers/_search
{
"query": {
"nested": {
"path": "driver",
"query": {
"nested": {
"path": "driver.vehicle",
"query": {
"bool": {
"must": [
{ "match": { "driver.vehicle.make": "Powell Motors" } },
{ "match": { "driver.vehicle.model": "Canyonero" } }
]
}
}
}
}
}
}
} Запрос возвращает следующий ответ:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 3.7349272,
"hits" : [
{
"_index" : "drivers",
"_id" : "1",
"_score" : 3.7349272,
"_source" : {
"driver" : {
"last_name" : "McQueen",
"vehicle" : [
{
"make" : "Powell Motors",
"model" : "Canyonero"
},
{
"make" : "Miller-Meteor",
"model" : "Ecto-1"
}
]
}
}
}
]
}
}
must_not и nested запросы
Если запрос nested соответствует одному или нескольким вложенным объектам в документе, он возвращает документ как результат. Это применимо даже если другие вложенные объекты в документе не соответствуют запросу. Имейте это в виду при использовании запроса nested, который содержит внутреннее условие must_not.
Используйте параметр inner_hits, чтобы увидеть, какие вложенные объекты соответствуют запросу nested.
Например, следующий запрос использует внешний запрос nested с внутренним условием must_not.
resp = client.indices.create(
index="my-index",
mappings={
"properties": {
"comments": {
"type": "nested"
}
}
},
)
print(resp)
resp1 = client.index(
index="my-index",
id="1",
refresh=True,
document={
"comments": [
{
"author": "kimchy"
}
]
},
)
print(resp1)
resp2 = client.index(
index="my-index",
id="2",
refresh=True,
document={
"comments": [
{
"author": "kimchy"
},
{
"author": "nik9000"
}
]
},
)
print(resp2)
resp3 = client.index(
index="my-index",
id="3",
refresh=True,
document={
"comments": [
{
"author": "nik9000"
}
]
},
)
print(resp3)
resp4 = client.search(
index="my-index",
query={
"nested": {
"path": "comments",
"query": {
"bool": {
"must_not": [
{
"term": {
"comments.author": "nik9000"
}
}
]
}
}
}
},
)
print(resp4) response = client.indices.create(
index: 'my-index',
body: {
mappings: {
properties: {
comments: {
type: 'nested'
}
}
}
}
)
puts response
response = client.index(
index: 'my-index',
id: 1,
refresh: true,
body: {
comments: [
{
author: 'kimchy'
}
]
}
)
puts response
response = client.index(
index: 'my-index',
id: 2,
refresh: true,
body: {
comments: [
{
author: 'kimchy'
},
{
author: 'nik9000'
}
]
}
)
puts response
response = client.index(
index: 'my-index',
id: 3,
refresh: true,
body: {
comments: [
{
author: 'nik9000'
}
]
}
)
puts response
response = client.search(
index: 'my-index',
body: {
query: {
nested: {
path: 'comments',
query: {
bool: {
must_not: [
{
term: {
'comments.author' => 'nik9000'
}
}
]
}
}
}
}
}
)
puts response const response = await client.indices.create({
index: "my-index",
mappings: {
properties: {
comments: {
type: "nested",
},
},
},
});
console.log(response);
const response1 = await client.index({
index: "my-index",
id: 1,
refresh: "true",
document: {
comments: [
{
author: "kimchy",
},
],
},
});
console.log(response1);
const response2 = await client.index({
index: "my-index",
id: 2,
refresh: "true",
document: {
comments: [
{
author: "kimchy",
},
{
author: "nik9000",
},
],
},
});
console.log(response2);
const response3 = await client.index({
index: "my-index",
id: 3,
refresh: "true",
document: {
comments: [
{
author: "nik9000",
},
],
},
});
console.log(response3);
const response4 = await client.search({
index: "my-index",
query: {
nested: {
path: "comments",
query: {
bool: {
must_not: [
{
term: {
"comments.author": "nik9000",
},
},
],
},
},
},
},
});
console.log(response4); PUT my-index
{
"mappings": {
"properties": {
"comments": {
"type": "nested"
}
}
}
}
PUT my-index/_doc/1?refresh
{
"comments": [
{
"author": "kimchy"
}
]
}
PUT my-index/_doc/2?refresh
{
"comments": [
{
"author": "kimchy"
},
{
"author": "nik9000"
}
]
}
PUT my-index/_doc/3?refresh
{
"comments": [
{
"author": "nik9000"
}
]
}
POST my-index/_search
{
"query": {
"nested": {
"path": "comments",
"query": {
"bool": {
"must_not": [
{
"term": {
"comments.author": "nik9000"
}
}
]
}
}
}
}
} Запрос возвращает:
{
...
"hits" : {
...
"hits" : [
{
"_index" : "my-index",
"_id" : "1",
"_score" : 0.0,
"_source" : {
"comments" : [
{
"author" : "kimchy"
}
]
}
},
{
"_index" : "my-index",
"_id" : "2",
"_score" : 0.0,
"_source" : {
"comments" : [
{
"author" : "kimchy"
},
{
"author" : "nik9000"
}
]
}
}
]
}
} | Этот вложенный объект соответствует запросу. В результате запрос возвращает родительский документ объекта как результат. | |
| Этот вложенный объект не соответствует запросу. Поскольку другой вложенный объект в том же документе соответствует запросу, запрос все равно возвращает родительский документ как результат. |
Чтобы исключить документы с вложенными объектами, которые соответствуют запросу nested, используйте внешнее условие must_not.
resp = client.search(
index="my-index",
query={
"bool": {
"must_not": [
{
"nested": {
"path": "comments",
"query": {
"term": {
"comments.author": "nik9000"
}
}
}
}
]
}
},
)
print(resp) response = client.search(
index: 'my-index',
body: {
query: {
bool: {
must_not: [
{
nested: {
path: 'comments',
query: {
term: {
'comments.author' => 'nik9000'
}
}
}
}
]
}
}
}
)
puts response const response = await client.search({
index: "my-index",
query: {
bool: {
must_not: [
{
nested: {
path: "comments",
query: {
term: {
"comments.author": "nik9000",
},
},
},
},
],
},
},
});
console.log(response); POST my-index/_search
{
"query": {
"bool": {
"must_not": [
{
"nested": {
"path": "comments",
"query": {
"term": {
"comments.author": "nik9000"
}
}
}
}
]
}
}
} Запрос возвращает:
{
...
"hits" : {
...
"hits" : [
{
"_index" : "my-index",
"_id" : "1",
"_score" : 0.0,
"_source" : {
"comments" : [
{
"author" : "kimchy"
}
]
}
}
]
}
}
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/query-dsl-nested-query.html