类型和映射
在ES中映射类似关系型数据库中的schema,描述了文档中有哪些字段和字段的类型,如string,data,int等。而 类型 是一组具有相关性的映射组成,然后使用"properties"来表示该类型中可能包含的字段属性。
具体如下:
{
"data": {
"mappings": {
"people": {
"properties": {
"name": {
"type": "string",
},
"address": {
"type": "string"
}
}
},
"transactions": {
"properties": {
"timestamp": {
"type": "date",
"format": "strict_date_optional_time"
},
"message": {
"type": "string"
}
}
}
}
}
}
在索引 data 中包含了两个类型,people 和 transactions,在类型people中,有两个字段:name 和 address,且都是string类型。在类型transactions中有也有两个字段,date类型的timestamp 和 string类型的message。
ES是如何映射Lucene的
我们都知道ES是基于Lucene实现的,ES中的映射和类型最终都会转化成Lucene中的字段类型的规范。
在ES里,文档以JSON格式存储数据,可以表达出层次结构,如上面索引data中的文档就有丰富的数据结构。而在Lucene中是没有类型和映射的概念的,ES的文档内容在Lucene中全部都被扁平化为键值对类型,ES中类型信息用字段_type字段来表示,上面ES中索引data的数据存在Lucene中的数据结构大致 如下:
{
"data": {
"mappings": {
"_type": {
"type": "string",
"index": "not_analyzed"
},
"name": {
"type": "string"
}
"address": {
"type": "string"
}
"timestamp": {
"type": "long"
}
"message": {
"type": "string"
}
}
}
}
在此结构类型下,name,address,timestamp和message在同一层级下,并使用 _type 字段来表示ES中的类型。
这是可能会有小伙伴会有这样的疑问:ES中data索引有两种类型:people 和
transactions 那在Lucene的_type字段只有一个,该如何表示呢?其实,在ES中每次索引数据时,会指定类型,因此每次只会索引一种类型的数据,所以 在Lucene中每个文档只有一个类型。
不过细心的小伙伴可能会发现Lucene的这种数据存储结构会存在以下两个问题:
1.ES中不同类型中,如果数据字段名称 相同会怎样
2.ES中每次索引一种类型的数据,在Lucene中会造成其他类型字段空间浪费。
对于第一个问题,如果在ES中不同 类型中有同名字段,且类型不同话,其实ES是不允许的,这样的配置会报错,例如在上文data索引中,在transactions和people类型中如果都定义了length字段,在people类型中length字段类型为string,在transactions类型中length字段类型为long,那么映射到Lucene中的话,就会变成有两个length字段,且类型不同,在进行文档索引中,就会产生歧义。因此这种配置,在索引映射配置时就是不允许的。
对于第二个问题,如果在ES中,同一索引中存在多种类型,因为每次索引文档时会指定类型,因此只有这个类型中字段会被填充数据,其他字段字段都会空的,如果两个类型的字段集是互不相同的,这就意味着索引中将有一半的数据是空的(字段将是 稀疏的 ),最终将导致性能问题。在这种情况下,最好是使用两个单独的索引。