内部对象(扁平式)
所有的信息都在一个文档中,比较高效.但是也有扁平式带来的问题,我们来试试!
//新建一个索引先,class_number是班级,student_info是学生信息,模拟一个一对多的场景
PUT flat_type
{
"mappings": {
"properties": {
"class_number": {
"type":"keyword"
},
"student_info":{
"properties":{
"student_name":{
"type":"keyword"
},
"student_age":{
"type":"keyword"
}
}
}
}
}
}
//插入一条数据,小明(xiaoming) 红红(honghong)
POST flat_type/_doc/1
{
"class_number": "1-1",
"student_info": [
{
"student_name": "xiaoming",
"student_age":11
},
{
"student_name": "honghong",
"student_age":10
}
]
}
//查询的条件是复合条件,必须要有student_info.student_age匹配到11,student_info.student_name匹配到红红
GET flat_type/_search
{
"query": {
"bool": {
"must": [
{"match": {
"student_info.student_age": 11
}},
{"match": {
"student_info.student_name": "honghong"
}}
]
}
}
}
//结果集
{
"took" : 8,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.723315,
"hits" : [
{
"_index" : "flat_type",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.723315,
"_source" : {
"class_number" : "1-1",
"student_info" : [
{
"student_name" : "xiaoming",
"student_age" : 11
},
{
"student_name" : "honghong",
"student_age" : 10
}
]
}
}
]
}
}
可以看到以上实验,他查询出了这个结果!并不是我们想要的结果!
小明应该是age11,红红应该是age10.
因为json格式的文档被处理成了扁平式的键值对的结构
student_info.student_name:["xiaoming","honghong"]
student_age.age:[11,10]
如果你的数据对于这种层级关系不敏感,可以选用这种方式
内嵌文档
我们还是用班级和学生信息当做例子来看看
内嵌文档nested的功能
//新建一个含有nested类型的索引
PUT nested_document
{
"mappings": {
"properties": {
"class_number": {
"type":"keyword"
},
"student_info":{
"type": "nested"
}
}
}
}
//新建文档1,班级1-1,小明(xiaoming)11岁,红红(honghong)10岁
POST nested_document/_doc/1
{
"class_number": "1-1",
"student_info": [
{
"student_name": "xiaoming",
"student_age":11
},
{
"student_name": "honghong",
"student_age":10
}
]
}
//新建文档2,班级1-2,小明12岁,红红13岁
POST nested_document/_doc/2
{
"class_number": "1-2",
"student_info": [
{
"student_name": "xiaoming",
"student_age":12
},
{
"student_name": "honghong",
"student_age":13
}
]
}
//查询会稍有变化,会多加一个nested层级
按照上面介绍的内部对象
我们的条件红红11岁是可以查出来的(因为扁平化文档对象了)
我们试试nested会不会有一样的情况
GET nested_document/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"class_number": "1-1"
}
},
{
"nested": {
"path": "student_info",
"query": {
"bool": {
"must": [
{
"match": {
"student_info.student_age": "11"
}
},
{
"match": {
"student_info.student_name": "xiaohong"
}
}
]
}
}
}
}
]
}
}
}
//结果集,很显然是没有
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
}
}
//我们再来修改成对的数据查询试试
红红其实是10岁
GET nested_document/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"class_number": "1-1"
}
},
{
"nested": {
"path": "student_info",
"query": {
"bool": {
"must": [
{
"match": {
"student_info.student_age": "10"
}
},
{
"match": {
"student_info.student_name": "honghong"
}
}
]
}
}
}
}
]
}
}
}
//结果集,是查出来了
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.3862944,
"hits" : [
{
"_index" : "nested_document",
"_type" : "_doc",
"_id" : "1",
"_score" : 2.3862944,
"_source" : {
"class_number" : "1-1",
"student_info" : [
{
"student_name" : "xiaoming",
"student_age" : 11
},
{
"student_name" : "honghong",
"student_age" : 10
}
]
}
}
]
}
}
nested其实在文档底层也是将nested内部的文档拆成了多份
我们可以查看一下文档的数量
GET _cat/indices/nested_document?v
//结果集
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open nested_document rBXvWV06R-ujhkz0ZCLQXg 1 1 6 0 17.8kb 8.9kb
文档数量是6,并不是2,我们再使用count看看
GET nested_document/_count
//结果集
{
"count" : 2,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
}
}
可以看到,文档数量是2
所以真实的文档数量其实是6,es内部其实是做过join的处理