文章目录世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。
-侯氏工坊
检索内部命中选项嵌套内部命中嵌套的内部命中和_source嵌套对象字段和内部命中的分层级别父/子内部命中参考
检索内部命中父连接和嵌套特性允许返回在不同范围内具有匹配项的文档。在父/子情况下,根据子文档中的匹配返回父文档,或者根据父文档中的匹配返回子文档。在嵌套的情况下,文档根据嵌套内部对象中的匹配项返回。在这两种情况下,导致返回文档的不同作用域中的实际匹配都是隐藏的。在许多情况下,知道是哪个内部嵌套对象(在嵌套的情况下)或子/父文档(在父/子的情况下)导致了某些信息的返回是非常有用的。内部点击功能可以用于此。这个特性在搜索响应中为每个搜索命中返回额外的嵌套命中,这些命中导致搜索命中在不同的范围中匹配。内部命中可以通过在嵌套、has_child或has_parent查询和过滤器上定义inner_hits定义来使用。结构是这样的:
"" : { "inner_hits" : { } }
如果inner_hits定义在一个支持它的查询上,那么每个搜索命中将包含一个inner_hits json对象,结构如下:
"hits": [
{
"_index": ...,
"_type": ...,
"_id": ...,
"inner_hits": {
"": {
"hits": {
"total": ...,
"hits": [
{
"_type": ...,
"_id": ...,
...
},
...
]
}
}
},
...
},
...
]
选项
内部命中支持一下选项:
|选项|描述|
|-|-|
|from|在返回的常规搜索命中中,获取每个inner_hits的第一个命中的位置的偏移量。|
|size|每个inner_hits返回的最大命中数。默认情况下,返回前3个匹配命中。|
|sort|内部命中应该如何排序。默认情况下,命中数是按分数排序的。|
|name|响应中用于特定内部命中定义的名称。当在一个搜索请求中定义了多个内部命中时非常有用。默认值取决于定义内部命中的查询。对于has_child query和filter,这是子类型,has_parent query和filter,这是父类型,而嵌套查询和filter,这是嵌套路径。|
内部点击还支持以下每个文档特性:
HighlightingExplainSearch fieldsSource filteringscript fieldsDoc value fieldsInclude versionsInclude Sequence Numbers and Primary Terms 嵌套内部命中
嵌套的inner_hits可以用来包含嵌套的内部对象作为搜索命中的内部命中。
PUT test
{
"mappings": {
"properties": {
"comments": {
"type": "nested"
}
}
}
}
PUT test/_doc/1?refresh
{
"title": "Test title",
"comments": [
{
"author": "kimchy",
"number": 1
},
{
"author": "nik9000",
"number": 2
}
]
}
POST test/_search
{
"query": {
"nested": {
"path": "comments",
"query": {
"match": { "comments.number": 2 }
},
"inner_hits": {}
}
}
}
下面是一个响应片段的例子,可以从上面的搜索请求中生成:
{
...,
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": ...,
"inner_hits": {
"comments": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "1",
"_nested": {
"field": "comments",
"offset": 1
},
"_score": 1.0,
"_source": {
"author": "nik9000",
"number": 2
}
}
]
}
}
}
}
]
}
}
_nested元数据在上面的例子中非常重要,因为它定义了这个内部命中来自哪个内部嵌套对象。该字段定义了嵌套命中的对象数组字段以及相对于它在_source中的位置的偏移量。由于排序和评分,inner_hits中命中对象的实际位置通常与定义嵌套内部对象的位置不同。默认情况下,_source也会为inner_hits中的命中对象返回,但这是可以更改的。通过_source过滤特性可以返回或禁用source的一部分。如果存储的字段定义在嵌套级别,这些也可以通过字段特性返回。一个重要的默认值是,inner_hits内部返回的_source是相对于_nested元数据的。因此,在上面的示例中,每次嵌套命中只返回comments部分,而不返回包含comments的顶级文档的整个源代码。 嵌套的内部命中和_source
嵌套文档没有_source字段,因为整个文档的source文件存储在根文档的_source字段下。为了只包含嵌套文档的source,将解析根文档的source,并且只将嵌套文档的相关位作为source包含在内部命中。对于每个匹配的嵌套文档这样做会影响执行整个搜索请求所需的时间,特别是当大小和内部命中的大小设置为高于默认值时。为了避免嵌套内部命中的相对昂贵的source提取,可以禁用包含source,只依赖doc values字段。像这样:
PUT test
{
"mappings": {
"properties": {
"comments": {
"type": "nested"
}
}
}
}
PUT test/_doc/1?refresh
{
"title": "Test title",
"comments": [
{
"author": "kimchy",
"text": "comment text"
},
{
"author": "nik9000",
"text": "words words words"
}
]
}
POST test/_search
{
"query": {
"nested": {
"path": "comments",
"query": {
"match": { "comments.text": "words" }
},
"inner_hits": {
"_source": false,
"docvalue_fields": [
"comments.text.keyword"
]
}
}
}
}
嵌套对象字段和内部命中的分层级别
如果映射有多层嵌套的对象字段,每一层都可以通过点标记的路径访问。例如,如果有一个comments嵌套字段包含一个votes嵌套字段,votes应该直接返回根命中,然后可以定义以下路径:
PUT test
{
"mappings": {
"properties": {
"comments": {
"type": "nested",
"properties": {
"votes": {
"type": "nested"
}
}
}
}
}
}
PUT test/_doc/1?refresh
{
"title": "Test title",
"comments": [
{
"author": "kimchy",
"text": "comment text",
"votes": []
},
{
"author": "nik9000",
"text": "words words words",
"votes": [
{"value": 1 , "voter": "kimchy"},
{"value": -1, "voter": "other"}
]
}
]
}
POST test/_search
{
"query": {
"nested": {
"path": "comments.votes",
"query": {
"match": {
"comments.votes.voter": "kimchy"
}
},
"inner_hits" : {}
}
}
}
结果如下
{
...,
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.6931471,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "1",
"_score": 0.6931471,
"_source": ...,
"inner_hits": {
"comments.votes": {
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 0.6931471,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "1",
"_nested": {
"field": "comments",
"offset": 1,
"_nested": {
"field": "votes",
"offset": 0
}
},
"_score": 0.6931471,
"_source": {
"value": 1,
"voter": "kimchy"
}
}
]
}
}
}
}
]
}
}
这种间接引用只支持嵌套的内部命中。 父/子内部命中
父/子inner_hits可以用来包含父/子元素:
PUT test
{
"mappings": {
"properties": {
"my_join_field": {
"type": "join",
"relations": {
"my_parent": "my_child"
}
}
}
}
}
PUT test/_doc/1?refresh
{
"number": 1,
"my_join_field": "my_parent"
}
PUT test/_doc/2?routing=1&refresh
{
"number": 1,
"my_join_field": {
"name": "my_child",
"parent": "1"
}
}
POST test/_search
{
"query": {
"has_child": {
"type": "my_child",
"query": {
"match": {
"number": 1
}
},
"inner_hits": {}
}
}
}
下面是一个响应片段的例子,可以从上面的搜索请求中生成:
{
...,
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {
"number": 1,
"my_join_field": "my_parent"
},
"inner_hits": {
"my_child": {
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.0,
"hits": [
{
"_index": "test",
"_type": "_doc",
"_id": "2",
"_score": 1.0,
"_routing": "1",
"_source": {
"number": 1,
"my_join_field": {
"name": "my_child",
"parent": "1"
}
}
}
]
}
}
}
}
]
}
}
参考
Retrieve inner hits深入学习访问基础篇和高级篇所有栏目内容参考栏目预告



