文章目录
Mapping官网文档: https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
Mapping是什么
mapping映射定义索引中有什么字段、字段的类型等结构信息。相当于数据库中表结构定义,或 solr中的schema。因为lucene索引文档时需要知道该如何来索引存储文档的字段。
ES中支持手动定义映射和动态映射两种方式。如下就是我们在创建索引时,手动自定义的映射:
PUT test { #定义索引名称为test
"mappings" : { #映射定义
"_doc" : { #名为_doc的映射类别
"properties" : { #字段定义
"field1" : { "type" : "text" } #名为field1的字段
}
}
}
}
映射类别废除说明
ES最先的设计是用索引类比关系型数据库的数据库,用mapping type 来类比表,一个索引中可以包含多个映射类别。这个类比存在一个严重的问题,就是当多个mapping type中存在同名字段时(特别是同名字段还是不同类型的),在一个索引中不好处理,因为搜索引擎中只有 索引-文档的结构,不同映射类别的数据都是一个一个的文档(只是包含的字段不一样而已)
从6.0.0开始限定仅包含一个映射类别定义( “index.mapping.single_type”: true ),兼容5.x中的多映射类别,从7.0开始将移除映射类别。为了与未来的规划匹配,请现在将这个唯一的映射类别名定义为_doc,因为索引的请求地址将规范为:
- PUT {index}/_doc/{id}
- POST {index}/_doc
Mapping映射实例:
PUT twitter {
"mappings": {
"_doc": {
"properties": {
"type": { "type": "keyword" },
"name": { "type": "text" },
"user_name": { "type": "keyword" },
"email": { "type": "keyword" },
"content": { "type": "text" },
"tweeted_at": { "type": "date" }
}
}
}
}
字段类型
字段类型定义了该如何索引存储字段值。ES中提供了丰富的字段类型定义,官网地址:
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
有常用的核心类型、复合类型、地理数据类型、特殊类型
这里说明下几个常用的字段类型。
text和keyword
这两个字段都是对应string类型的,但是有区别:
- text类型主要用于分词,比如新闻标题、描述,不能进行排序和聚合
- keyword类型主要用于排序和聚合,比如新闻类型、商品类别
因此如果一个字段被定义成了text类型,则就不能进行排序了,如果一个字段既需要分词、有需要排序或聚合,则可以将该字段定义成Multi-fields
Multi-fields多重字段
当我们需要对一个字段进行多种不同方式的索引时,可以使用fields多重字段定义。如一个字符串字段即需要进行text分词索引,也需要进行keyword 关键字索引来支持排序、聚合,或需要用不同的分词器进行分词索引。
官网提供了一个例子,可以尝试一下:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
}
PUT my_index/_doc/1
{
"city": "New York"
}
PUT my_index/_doc/2
{
"city": "York"
}
GET my_index/_search
{
"query": {
"match": {
"city": "york"
}
},
"sort": {
"city.raw": "asc"
},
"aggs": {
"Cities": {
"terms": {
"field": "city.raw"
}
}
}
}
- raw是一个自定义的多重字段名
- 在进行排序查询的时候,会将整个_source的内容进行排序,而不是对分词后的结果进行排序
字段其他属性
字段的type定义了如何索引存储该字段,字段类型默认会设置是否存储、索引、分词器等,我们可以定义其他属性让我们根据需要来覆盖默认的值或进行特别定义。
官网地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-params.html
比如以下示例:
PUT my_index {
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
}
- format属性定义该时间字段如何格式化
- 上述定义表示上传的字段date必须符合三种格式中的一种,ES内部会将时间全部转换为long类型的毫秒数
元数据
Identity meta-fields
标识元字段
- _index:该文档所属的索引index
- _uid:_type和_id组合而成的复合字段
- _type:该文档的mapping type,以后统一为_doc
- _id:该文档的id,可以用上传数据的唯一主键充当,也可以es内部自己生成
Document source meta-fields
文档源元字段
- _source:是否存储文档的原JSON对象,默认是true存储
- _size:_source原JSON对象的大小,单位字节数
Indexing meta-fields
- _all:复制文档的其他字段值到这一个字段上进行索引,默认禁用。6.0以后版本废弃该字段,改用copy-to
Routing meta-fields
- _routing:自定义的路由值,决定将文档路由到哪个分片上,默认是用_id,路由的计算方式:shard_num = hash(_routing) % num_primary_shards
动态映射
动态映射:ES中提供的重要特性,让我们可以快速使用ES,而不需要先创建索引、定义映射。 如我们直接向ES提交文档进行索引:
PUT data/_doc/1 {
"count": 5
}
ES将自动为我们创建data索引、_doc 映射、类型为 long 的字段 count。然后下次再索引文档时,当有新字段时, ES将根据我们字段的json的数据类型为我们自动加入字段定义到mapping中。
字段动态映射规则
Date detection 时间侦测
时间侦测date_detection默认是开启的,当有一个内容提交上来时,ES会自动监测里面的字段是否符合时间格式,如果符合,则把它设置为时间类型。默认的时间格式dynamic_date_formats为:
[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss Z||yyyy/MM/dd Z"]
官方示例:
PUT my_index/_doc/1
{
"create_date": "2015/09/02"
}
GET my_index/_mapping
create_date字段会被自动添加为date类型,且format格式如下:
禁用时间侦测:
PUT my_index
{
"mappings": {
"_doc": {
"date_detection": false
}
}
}
自定义时间格式:
PUT my_index
{
"mappings": {
"_doc": {
"dynamic_date_formats": ["MM/dd/yyyy"]
}
}
}
Numeric detection 数值侦测
数值侦测默认是关闭的。数值侦测会对上传上来的内容进行监测,会对数值类型的字符串进行自动转换,官网的例子如下:
PUT my_index
{
"mappings": {
"_doc": {
"numeric_detection": true
}
}
}
PUT my_index/_doc/1
{
"my_float": "1.0",
"my_integer": "1"
}