淘先锋技术网

首页 1 2 3 4 5 6 7

参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/nested.html

举例

PUT my_index/_doc/1
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

在索引index中,存入user的数据,最终 es 会将上述数据,扁平化处理,实际存储如下这样子:

{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}

很明显,数据存储成这样子,丢失了first 和 last 之间关系。从这样的存储中,我们无法确定,first 为 “alice” 的对应的 last 是 “smith” 还是 “white”。

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}

如果数组里存储的是对象,那么数组的类型应该是 nested,这样,再将对象数据存入数组中时,对象便不会被扁平化处理。
执行如下查询:

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}

查询到的结果:

{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "group" : "fans",
          "user" : [
            {
              "first" : "John",
              "last" : "Smith"
            },
            {
              "first" : "Alice",
              "last" : "White"
            }
          ]
        }
      }
    ]
  }
}

查询到一条数据,而这样的数据并不是我们想要的。因为通过 "first" 为 "Alice""last" 为 "Smith",不应该查询到数据。之所以查询到数据,是因为数组中存储的对象被扁平化处理了。

修改索引的mapping信息,将user数组的类型定义为 nested 并存入数据,重新执行检索。

PUT my_index
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" 
      }
    }
  }
}

PUT my_index/_doc/1
{
  "group" : "fans",
  "user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

执行同样查询:

GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}

获取到的结果为空:

{
  "took" : 11,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

这样的结果才是我们想要的,这样防止了 frist 和 last 之间关系的丢失。