嵌套查询
`nested` 查询作为其他查询的包装器,用于搜索嵌套字段。嵌套字段对象被搜索时,就好像它们被索引为单独的文档一样。如果某个对象匹配搜索,`nested` 查询将返回根级别的父文档。
示例
在运行 `nested` 查询之前,您的索引必须包含一个嵌套字段。
要配置包含嵌套字段的示例索引,请发送以下请求:
PUT /testindex
{
"mappings": {
"properties": {
"patient": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
}
}
}
}
}
}
接下来,将一个文档索引到示例索引中:
PUT /testindex/_doc/1
{
"patient": {
"name": "John Doe",
"age": 56
}
}
要搜索嵌套的 `patient` 字段,请将您的查询包装在一个 `nested` 查询中,并提供嵌套字段的 `path`:
GET /testindex/_search
{
"query": {
"nested": {
"path": "patient",
"query": {
"match": {
"patient.name": "John"
}
}
}
}
}
查询返回匹配的文档:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "testindex",
"_id": "1",
"_score": 0.2876821,
"_source": {
"patient": {
"name": "John Doe",
"age": 56
}
}
}
]
}
}
检索内部匹配项
要返回匹配查询的内部命中,请提供 `inner_hits` 参数:
GET /testindex/_search
{
"query": {
"nested": {
"path": "patient",
"query": {
"match": {
"patient.name": "John"
}
},
"inner_hits": {}
}
}
}
响应中包含额外的 `inner_hits` 字段。`_nested` 字段标识了内部命中源自的特定内部对象。它包含嵌套命中以及相对于其在 `_source` 中位置的偏移量。由于排序和评分,`inner_hits` 中命中对象的位置通常与其在嵌套对象中的原始位置不同。
默认情况下,`inner_hits` 中命中对象的 `_source` 是相对于 `_nested` 字段返回的。在此示例中,`inner_hits` 中的 `_source` 包含 `name` 和 `age` 字段,而不是包含整个 `patient` 对象的顶级 `_source`。
{
"took": 38,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "testindex",
"_id": "1",
"_score": 0.2876821,
"_source": {
"patient": {
"name": "John Doe",
"age": 56
}
},
"inner_hits": {
"patient": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.2876821,
"hits": [
{
"_index": "testindex",
"_id": "1",
"_nested": {
"field": "patient",
"offset": 0
},
"_score": 0.2876821,
"_source": {
"name": "John Doe",
"age": 56
}
}
]
}
}
}
}
]
}
}
您可以通过在映射中配置 `_source` 字段来禁用 `_source` 的返回。有关更多信息,请参阅源。
有关检索内部匹配项的更多信息,请参阅 内部匹配项。
多级嵌套查询
您可以使用多级嵌套查询来搜索包含其他嵌套对象的文档。在此示例中,您将通过为层次结构的每个级别指定一个嵌套查询来查询多层嵌套字段。
首先,创建一个包含多级嵌套字段的索引:
PUT /patients
{
"mappings": {
"properties": {
"patient": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"contacts": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"relationship": {
"type": "text"
},
"phone": {
"type": "keyword"
}
}
}
}
}
}
}
}
接下来,将一个文档索引到示例索引中:
PUT /patients/_doc/1
{
"patient": {
"name": "John Doe",
"contacts": [
{
"name": "Jane Doe",
"relationship": "mother",
"phone": "5551111"
},
{
"name": "Joe Doe",
"relationship": "father",
"phone": "5552222"
}
]
}
}
要搜索嵌套的 `patient` 字段,请使用多级 `nested` 查询。以下查询搜索联系信息中包含名为 `Jane` 且关系为 `mother` 的患者:
GET /patients/_search
{
"query": {
"nested": {
"path": "patient",
"query": {
"nested": {
"path": "patient.contacts",
"query": {
"bool": {
"must": [
{ "match": { "patient.contacts.relationship": "mother" } },
{ "match": { "patient.contacts.name": "Jane" } }
]
}
}
}
}
}
}
}
查询返回具有匹配这些详细信息的联系人条目的患者:
{
"took": 14,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.3862942,
"hits": [
{
"_index": "patients",
"_id": "1",
"_score": 1.3862942,
"_source": {
"patient": {
"name": "John Doe",
"contacts": [
{
"name": "Jane Doe",
"relationship": "mother",
"phone": "5551111"
},
{
"name": "Joe Doe",
"relationship": "father",
"phone": "5552222"
}
]
}
}
}
]
}
}
参数
下表列出了 `nested` 查询支持的所有顶级参数。
参数 | 必需/可选 | 描述 |
---|---|---|
路径 | 必需 | 指定要搜索的嵌套对象的路径。 |
query | 必需 | 对指定 `path` 内的嵌套对象运行的查询。如果嵌套对象匹配查询,则返回根父文档。您可以使用点表示法(例如 `nested_object.subfield`)搜索嵌套字段。支持多级嵌套并自动检测。因此,另一个嵌套查询内的内部 `nested` 查询会自动匹配正确的嵌套级别,而不是根级别。 |
ignore_unmapped | 可选 | 指示是否忽略未映射的 `path` 字段,不返回文档而是抛出错误。在查询多个索引时可以提供此参数,其中某些索引可能不包含 `path` 字段。默认值为 `false`。 |
score_mode | 可选 | 定义匹配的内部文档的分数如何影响父文档的分数。有效值有: - `avg`:使用所有匹配内部文档的平均相关性分数。 - `max`:将匹配内部文档中的最高相关性分数分配给父文档。 - `min`:将匹配内部文档中的最低相关性分数分配给父文档。 - `sum`:汇总所有匹配内部文档的相关性分数。 - `none`:忽略内部文档的相关性分数,并将父文档的分数设置为 `0`。 默认值为 `avg`。 |
inner_hits | 可选 | 如果提供,则返回匹配查询的底层命中。 |
后续步骤
- 了解更多关于 检索内部匹配项 的信息。