参考文档: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 之间关系的丢失。