映射(mapping)是定义文档及其包含字段的存储和索引方式的一组过程
字段映射需要考虑的问题:
1)、哪个string类型的字段应该作为全文索引;
2)、哪些字段应该包含数字,日期或者地理位置;
3)、日期类型值应该被如何格式化;
4)、自定义规则来控制动态添加字段的映射;
映射的定义包含以下两个部分:
1、ES索引结构元字段
标识元字段:表示文档相关元数据
序号 | 类型 | 说明 |
---|---|---|
1 | _index | 表示文档所属索引名称 |
2 | _type | 表示文档所属索引的类型名称,7.x之后均为_doc |
3 | _id | 文档唯一id |
文档数据元字段
序号 | 类型 | 说明 |
---|---|---|
1 | _source | 文档原始JSON数据 |
2 | _size | _source字段内容的字节大小(需安装mapper-size插件) |
索引元字段
序号 | 类型 | 说明 |
---|---|---|
1 | _field_names | 记录索引文档的所有non_null值的字段 |
2 | _ignored | 文档中所有在索引时指定无需索引字段(使用ignore_malformed标识) |
路由元字段
序号 | 类型 | 说明 |
---|---|---|
1 | _routing | 自定义路由值,将文档路由到指定分片 |
其它元字段
序号 | 类型 | 说明 |
---|---|---|
1 | _meta | 由应用指定的元数据,可看做应用的标识数据 |
2、文档内容属性
字段类型
1)、简单类型有text,keyword,date,long,double,boolean或ip;
2)、支持json分层的类型,如object或者nested;
3)、专门类型,如geo_point,geo_shape或completion;
实际场景中我们可能希望在不同场景以不同的方式使用相同的字段,这可以使用多字段(multi-fields)映射处理,例如一个string类型字段可以被映射成text字段以用于全文检索,同时也可以作为提个keyword类型用于排序或者聚合操作,甚至可以将同一个字段使用不同的分词器(standard analyzer、english analyzer、french analyzer)进行分词处理;
防止字段映射冲突的设置
同一个索引当中映射太多的字段可能会导致映射冲突,进而会导致内存不足以及数据无法恢复的情况;
在开启动态映射的情况下,若新插入的文档中有未被映射的字段,在插入之时新的字段将会添加到索引映射当中,这样随着映射的增加可能会导致问题;
以下设置可以限制索引映射字段的数量以防止产生映射冲突情况:
序号 | 类型 | 说明 |
---|---|---|
1 | index.mapping.total_fields.limit | 索引映射字段最大值,字段和对象的映射以及字段别名都计入此限制,默认值1000 |
2 | index.mapping.depth.limit | 索引字段的最大深度,以内部对象的数量衡量;若所有字段都在跟对象级别定义,则深度为1,若有一个对象映射,则深度为2,以此类推,默认值20; |
3 | index.mapping.nested_fields.limit | 索引中不同嵌套(nested)映射最大值,嵌套(nested)类型应该只用于特殊场景(对象数组的查询记录是相互独立的情况),为防止不良的映射,默认值50; |
4 | index.mapping.nested_objects.limit | 索引中单个文档可包含嵌套(nested)JSON对象的最大值,此参数可限制文档包含太多嵌套对象(可能会导致内存不足),默认值10000; |
5 | index.mapping.field_name_length.limit | 索引值字段名长度最大值,该设置并不能解决映射冲突的问题,但对于限制字段名长度来说是可用的;通常不需要配置此参数,除非添加的记录字段名称长度非常长,默认值Long.MAX_VALUE; |
动态映射
字段类型和映射类型不需要在使用前定义,通过动态映射,新的字段名通过索引会被自动映射,新的字段既可以映射为顶级类型,同时也可以映射为内部对象或嵌套类型;
显式映射
相较于ES的自动映射,处理数据的我们对于数据的熟悉程度肯定要比ES更多,故在一些特殊的场景下显式设置字段映射效果会更好;
1)、创建索引时指定字段类型
PUT /explicit_definition_index
{
"mappings": {
"properties": {
"age":{
"type": "integer"
},
"email":{
"type": "keyword"
},
"name":{
"type": "text"
}
}
}
}
2)、向索引中添加新字段
除了es支持修改的映射参数外,es不允许更改现有字段映射或字段类型,更改现有字段可能会使已经建立索引的数据无效;
若想更改映射中的字段,最好是创建一个新的索引并将原索引中数据导入到新的索引中;
重命名字段会使旧字段名称下已建立索引的数据无效,可以创建一个新的字段并将其类型置为alias;
//查看索引映射详情
GET /explicit_definition_index/_mapping
{
"explicit_definition_index" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "integer"
},
"email" : {
"type" : "keyword"
},
"name" : {
"type" : "text"
}
}
}
}
}
//查看映射字段详情
GET /explicit_definition_index/_mapping/field/age
{
"explicit_definition_index" : {
"mappings" : {
"age" : {
"full_name" : "age",
"mapping" : {
"age" : {
"type" : "integer"
}
}
}
}
}
}
移除索引的类型的原因
将ES对比DB是不恰当的比喻,在数据库当中,表与表之间是相互物理独立的,继而字段与字段之间也是相互独立的,但是在ES中并非如此,ES底层是基于Lucene做字段的存储,若不同的索引拥有相同的字段名称而其字段类型不同,在存储上都使用的是同一个字段名称,这可能会导致数据上的一些问题,最重要的是存储在同一索引中几乎没有或完全没有相同字段的数据会导致数据稀疏分布并干扰Lucene有效压缩文档的能力,基于以上原因决定需要移除索引的类型概念;
自定义type字段,可显式在索引中指定type字段以用于类型区分(如果有需要的话)
//索引数据迁移
// 新建索引
PUT /new_index
{
"settings": {
"index.mapping.single_type":true
},
"mappings": {
"_doc":{
"properties":{
}
}
}
}
// 索引数据迁移
POST _reindex
{
"source": {
"index": "",
"type": ""
},
"dest": {
"index": "new_index",
"type":"_doc"
}
}
// 自定义索引类型
POST _reindex
{
"source": {
"index": ""
},
"dest": {
"index": "new_index"
},
"script": {
"source": """
ctx._source.type = ctx._type;
ctx._id = ctx._type + '-' + ctx._id;
ctx._type = '_doc'
"""
}
}
参考文档
压缩技术:http://www.360doc.com/content/19/0722/00/40661497_850235499.shtml