概念介绍
- es中的object类型可理解为field包含field即field的分层结构。
- 例如下面的index,在第一个层次包含了[region,manager]字段,manager内部又包含了[age,name],name本身又是一个object,包含了[first,last]。
- 这里需要注意的是,name使用了dynamic、enabled、properties、type属性。
- 其中,dyanmic表示此object是否可动态添加字段,当然也可以给当前索引整体设置dyanmic的值;
- enabled表示是否此object可被索引,以作为后续检索使用;
- properties定义了内部下一层的fields;
- 这里需要关注的是type,type定义了此字段的数据类型,为object。manager没有使用type,是因为在这种情况下,object是默认值。
- 如果是field的分层结构及上面的manager不必显示的指明类型为object,但是如果类型指明为其他类型,则报错
- 这里要注意,manager作为外层的object,它的enabled属性不能设置为false,否则对于其内部的name object,即使其enabled设置为true,也不能被query检索到。
#manager没有显示的指明类型为object
PUT test_object
{"mappings": {
"properties": {
"region":{
"type": "keyword"
},
"manager":{
"dynamic":true,
"enabled":true,
"properties": {
"age":{
"type":"integer"
},
"name":{
"dynamic":false,
"enabled":true,
"type":"object",
"properties":{
"first":{
"type":"keyword"
},
"last":{
"type":"keyword"
}
}
}
}
}
}
}}
- es的底层是lucene,lucene是不识别object对象的,因此,在内部,object对象数据,是按照分层平展开来的
{
region,
manager.age,
manager.name.first,
manager,name,last
}
- 这样带来一个问题:作为一个整体存在的object,不能被作为整体单独检索
POST test_object/_doc
{
"region" : "region1",
"manager" : [
{
"age":23,
"name":[
{
"first" : "John",
"last" : "Smith"
}
]
},
{
"age":23,
"name":[
{
"first" : "Alice",
"last" : "White"
}
]
}
]
}//结构
{
"region":"region1"
"manager.age":[23,23]
"manager.name.first":["John","Alice"]
"manager.name.last":["Smith","White"]
}
- 如果我们要检索一个document,它需要满足这样的条件:first name = Alice ,并且last name = Smith:
//结构
{
"region":"region1"
"manager.age":[23,23]
"manager.name.first":["John","Alice"]
"manager.name.last":["Smith","White"]
}GET test_object/_search
{
"query": {
"bool": {
"must": [
{ "match": { "manager.name.first": "Alice" }},
{ "match": { "manager.name.last": "Smith" }}
]
}
}
}
- 从我们上面的数据来看,Alice与White为一个name object,John与Smith为一个name object。正常的话,是不能检索出来的,但是上面这个query却查询出了结果。原因就在于,在es(lucene)内部,这个数据是按照类似上述的方式展开存储的
dyanmic作用介绍
- manager的dyanmic设为true
- name的设为true
PUT test_object
{"mappings": {
"properties": {
"region":{
"type": "keyword"
},
"manager":{
"dynamic":true,
"enabled":true,
"properties": {
"age":{
"type":"integer"
},
"name":{
"dynamic":true,
"enabled":true,
"type":"object",
"properties":{
"first":{
"type":"keyword"
},
"last":{
"type":"keyword"
}
}
}
}
}
}
}}//新增mapping中不存在的字段
POST test_object/_doc/1
{
"region" : "region1",
"manager" : [
{
"age":23,
"name":[
{
"first" : "John",
"last" : "Smith",
"test_name":"test_name"
}
],
"test_manager":"test_manager"
},
{
"age":23,
"name":[
{
"first" : "Alice",
"last" : "White"
}
]
}
]
}//查看mapping文件,为新添加的字段设置了mapping映射(一般情况下不建议开启)
{
"test_object" : {
"mappings" : {
"properties" : {
"manager" : {
"dynamic" : "true",
"properties" : {
"age" : {
"type" : "integer"
},
"name" : {
"dynamic" : "true",
"properties" : {
"first" : {
"type" : "keyword"
},
"last" : {
"type" : "keyword"
},
"test_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"test_manager" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"region" : {
"type" : "keyword"
}
}
}
}
}//manager和name的dyanmic设为strict
PUT test_object
{"mappings": {
"properties": {
"region":{
"type": "keyword"
},
"manager":{
"dynamic":"strict",
"enabled":true,
"properties": {
"age":{
"type":"integer"
},
"name":{
"dynamic":"strict",
"enabled":true,
"type":"object",
"properties":{
"first":{
"type":"keyword"
},
"last":{
"type":"keyword"
}
}
}
}
}
}
}}//再次添加上述文档,错误提示
{
"error" : {
"root_cause" : [
{
"type" : "strict_dynamic_mapping_exception",
"reason" : "mapping set to strict, dynamic introduction of [test_name] within [manager.name] is not allowed"
}
],
"type" : "strict_dynamic_mapping_exception",
"reason" : "mapping set to strict, dynamic introduction of [test_name] within [manager.name] is not allowed"
},
"status" : 400
}//也可以整体设置
PUT /test_object/_mapping
{
"dynamic":"strict"
}