Elastic:查询数组时如何只返回匹配的数组元素

举报
wu@55555 发表于 2022/11/17 22:06:12 2022/11/17
【摘要】 ES的查询单位是doc,所以当我们查询数组时,虽然满足条件的是其中某一部分元素,但是这些元素以及这个数组都是属于这个doc的,所以会全部返回。如果我们要返回匹配的元素。那么就需要借助一些手段来实现。

1 数组查询

ES的查询单位是doc,所以当我们查询数组时,虽然满足条件的是其中某一部分元素,但是这些元素以及这个数组都是属于这个doc的,所以会全部返回。如果我们要返回匹配的元素。那么就需要借助一些手段来实现。
查询

GET arr_json/_search
{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "match": {
          "tags.name": "ok"
        }
      }
    }
  }
}

查询结果

"hits" : [
      {
        "_index" : "arr_json",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.9808291,
        "_source" : {
          "tags" : [
            {
              "id" : 1,
              "name" : "ok"
            },
            {
              "id" : 2,
              "name" : "fine"
            },
            {
              "id" : 3,
              "name" : "right"
            }
          ]
        }
      }
    ]

2 json型数组只返回匹配的数组元素

添加数据

PUT arr_json
{
  "mappings": {
    "properties": {
      "tags": {
        "type": "nested"
      }
    }
  }
}

PUT arr_json/_doc/1
{"tags":[
  {"id":1,"name":"ok"},
  {"id":2,"name":"fine"},
  {"id":3,"name":"right"}
  ]
}

通过inner_hit以及ignore_unmapped来实现:

GET arr_json/_search
{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "match": {
          "tags.name": "ok"
        }
      },
      "inner_hits": {
        "ignore_unmapped": false
      }
    }
  }
}

返回结果,注意要求的数据是在inner_hit中

{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.9808291,
    "hits" : [
      {
        "_index" : "arr_json",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.9808291,
        "_source" : {
          "tags" : [
            {
              "id" : 1,
              "name" : "ok"
            },
            {
              "id" : 2,
              "name" : "fine"
            },
            {
              "id" : 3,
              "name" : "right"
            }
          ]
        },
        "inner_hits" : {
          "tags" : {
            "hits" : {
              "total" : {
                "value" : 1,
                "relation" : "eq"
              },
              "max_score" : 0.9808291,
              "hits" : [
                {
                  "_index" : "arr_json",
                  "_type" : "_doc",
                  "_id" : "1",
                  "_nested" : {
                    "field" : "tags",
                    "offset" : 0
                  },
                  "_score" : 0.9808291,
                  "_source" : {
                    "name" : "ok",
                    "id" : 1
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

3 inner_hits解读

The parent-join and nested features allow the return of documents that have matches in a different scope. In the parent/child case, parent documents are returned based on matches in child documents or child documents are returned based on matches in parent documents. In the nested case, documents are returned based on matches in nested inner objects.

In both cases, the actual matches in the different scopes that caused a document to be returned are hidden. In many cases, it’s very useful to know which inner nested objects (in the case of nested) or children/parent documents (in the case of parent/child) caused certain information to be returned. The inner hits feature can be used for this. This feature returns per search hit in the search response additional nested hits that caused a search hit to match in a different scope.

Inner hits can be used by defining an inner_hits definition on a nested, has_child or has_parent query and filter. The structure looks like this:

"<query>" : {
  "inner_hits" : {
    <inner_hits_options>
  }
}

译文:
父连接和嵌套功能允许返回在不同范围内有匹配的文档。在父/子的情况下,父文档根据子文档中的匹配结果被返回,或者子文档根据父文档中的匹配结果被返回。在嵌套的情况下,文件是根据嵌套的内部对象中的匹配来返回的。

在这两种情况下,导致文档被返回的不同作用域中的实际匹配是隐藏的。在许多情况下,知道哪个内部嵌套对象(在嵌套的情况下)或子/父文档(在父/子的情况下)导致某些信息被返回是非常有用的。内部命中特征可以用于此。这个功能在搜索响应中返回每一个导致搜索命中在不同范围内匹配的额外嵌套命中。

内部命中可以通过在一个嵌套的,has_child或者has_parent查询和过滤器上定义一个inner_hits定义来使用。该结构看起来像这样。

"<query>" : {
  "inner_hits" : {
    <inner_hits_options>
  }
}

所以可以看出,inner_hits只适用nested和join结构的数据

4 简单数组只返回匹配的数组元素

PUT test3/_doc/1
{
  "tags": [
    "ok",
    "fine",
    "right"
  ]
}

简单数组是不能设置inner_hits的,这一点我查询了很多资料,并没有找到答案,最后咨询了业界大佬,了解到,简单数组目前并不支持这种操作

如果你有任何想法,也可以留言探讨

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。