关于inner_hits

2020-04-25  本文已影响0人  饿虎嗷呜

关于inner_hits

本文将从以下几个方面回答有关inner_hits的一些问题:

  1. 什么是inner_hits
  2. 为什么要有inner_hits
  3. 如何使用inner_hits

问题1,什么是inner_hits?

inner_hits是ElasticSearch进行nested,has_parent,has_child搜索时的一个选项,用来标记命中文档位置的。以官方文档中的例子为例。

PUT blog
{
  "mappings": {
    "properties": {
      "comments": {
        "type": "nested"
      }
    }
  }
}


PUT blog/_doc/1?refresh
{
  "title": "Test title",
  "comments": [
    {
      "author": "kimchy",
      "number": 1
    },
    {
      "author": "nik9000",
      "number": 2
    }
  ]
}

索引”blog“有一个类型为”nested“的字段”comments“,我们写入了一个文档,其中包含了2个”comments“。下面我们对文档进行搜索,我们先不添加”inner_hits“看一下结果是怎么样:

POST test/_search
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "match": {
          "comments.number": "2"
        }
      }
    }
  }
}

.....

    "hits" : [
      {
        "_index" : "test",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "title" : "Test title",
          "comments" : [
            {
              "author" : "kimchy",
              "number" : 1
            },
            {
              "author" : "nik9000",
              "number" : 2
            }
          ]
        }
      }
    ]

可以看到,这个结果和正常搜索没有太多区别。

现在我们在搜索时加入”inner_hits“看一下效果,为了简单起见,”inner_hits“不使用任何选项。

POST test/_search
{

  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "match": {
          "comments.number": 2
          }
      },
      "inner_hits": {
      }
    }
  }
}

我们可以看到结果比刚才多了一个”inner_hits“块:

        "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
                  }
                }
              ]
            }
          }
        }

可以看到,”inner_hits“中包含了关于此处文档的一些匹配信息,其中比较重要的有两个:

”nested“,告诉我们此次命中是文档中的那个nested字段,我们的例子里只有一个”nested“类型的字段,而实际上一个索引中,默认最多可以有50个”nested“类型的字段,这个值由索引的配置项”index.mapping.nested_fields.limit“控制。

”_source“,告诉我们当前命中的是哪个文档。我们的例子里,查询的条件是”number=2“,因此在 ”_source“部分返回了对应的那个文档。“inner_hits”有一个选项“_source”,默认值是true,如果将其置为false可以在返回结果中不显示”_source“的内容。

问题2,为什么要使用inner_hits?

在ElasticSearch中,nested对象是以独立的隐藏文档的方式进行存储的,以上面的例子为例,id为1的文档,有2个comments类型的nested对象,最终存储在ES中的其实是三个文档。而relation类型的对象,父子文档的结构可以完全不同,却是存储在同一个索引中。在进行nested search或者has_child,has_parent search的时候我们可能需要知道,我们的搜索到底是匹配了哪些更细粒度的文档。因此需要inner_hits。

问题3,怎样使用inner_hits

最简单的用法,如上文例子中使用的一样。直接加入一个空的“inner_hits”块即可。除此之外还有一些更细粒度的控制选项:

"from": 指定从文档内部对象array的某个位置开始显示inner_hits。比如说如果from指定为2,那么位置在0和1的文档即使在搜索中被匹配到了,也不会显示在inner_hits里。

"size": 最多显示inner_hits的文档数。

"sorted": 返回inner_hits 对象的排序字段。

"name": 当存在有多个nested字段在搜索中被涉及到时,指定其中某个字段作为inner_hits的显示字段。

更多可参考官方文档的内容

https://www.elastic.co/guide/en/elasticsearch/reference/7.2/search-request-inner-hits.html

小结

由于nested search,has_parent search,has_child search的文档对象存储方式,在进行相关搜索时,会涉及到主文档之外的其他文档,我们需要一种手段来指出命中的原因。inner_hits应运而生,它可以支持命中文档在多个文档组成的array中的位置,以及具体是哪个nested对象被命中了。总而言之,这是一种帮助我们理解搜索结果的方式或者手段。

上一篇下一篇

猜你喜欢

热点阅读