数据库建表的时候,咱们的DDL语句通常都会指定每一个字段的存储类型,例如:varchar,int,datetime等等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱。html
CREATE TABLE `shop_` ( `id_` varchar(36) NOT NULL COMMENT 'id', `shop_name_` varchar(50) DEFAULT NULL COMMENT '商品名称', `shop_integral_` int(11) DEFAULT NULL COMMENT '兑换所需积分', `shop_money_` decimal(10,0) DEFAULT NULL COMMENT '劵面金额', `start_time_` datetime DEFAULT NULL COMMENT '有效开始时间', `end_time_` datetime DEFAULT NULL COMMENT '有效结束时间', `is_delete_` int(1) DEFAULT '1' COMMENT '是否删除-1:有效,0:删除', PRIMARY KEY (`id_`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
在 Elasticsearch中也是这样,建立索引的时候通常也须要指定索引的字段类型,这种方式成为映射(Mapping)。sql
映射(Mapping)针对的是文档的字段,数据库中有varchar,int,datetime等数据类型,那么咱们ElasticSearch中又有哪些字段类型,每一个字段类型都表明什么意思呢?数据库
ElasticSearch更新频繁,如下内容是针对6.x版本的,对于5.x版本以及以前的版本可能有所不一样,将来7.x版本也许也会有所改变,本篇不能作到面面俱到,因此你们能够针对本身的版本查阅官方文档。json
Elasticsearch支持文档字段的多种不一样数据类型,根据官方文档的分类,能够划分为如下几个类别:
核心数据类型,复杂数据类型,Geo(地理)数据类型,专用数据类型和多字段。数组
这里咱们重点介绍下 text 和 keyword 的区别:app
text 用于索引全文值的字段,例如电子邮件正文或产品说明。这些字段是analyzed,它们经过分词器传递 ,以在被索引以前将字符串转换为单个术语的列表。分析过程容许Elasticsearch搜索单个单词中 每一个完整的文本字段。文本字段不用于排序,不多用于聚合(尽管 重要的文本聚合 是一个值得注意的例外)。elasticsearch
keyword 用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。它们一般用于过滤,排序,和聚合。keyword字段只能按其确切值进行搜索。若是您须要索引电子邮件正文或产品说明等全文内容,则可能应该使用text字段。ide
有时候一个字段同时拥有全文类型(text)和关键字类型(keyword)是有用的:一个用于全文搜索,另外一个用于聚合和排序。这能够经过多字段类型来实现。ui
有时候单纯的一个字段类型知足不了咱们复杂的需求,为了避免同的目的,以不一样的方式索引同一个字段一般颇有用。多字段也是ES的一种数据类型,只不过结合了更多的功能。编码
例如,对于字符串字段,咱们既能够将它映射为text类型用于全文搜索,亦能够将它映射为keyword类型用于排序或聚合,或者,还可使用标准分词器、英语分词器和其余语言分词器索引文本字段。
大多数数据类型都经过fields
参数支持多字段。例如对于城市名称的多字段映射,能够这样写:
PUT my_index { "mappings": { "_doc": { "properties": { "cityName": { "type": "text", "fields": { "raw": { "type": "keyword" } } } } } } }
Elasticsearch的字段类型讲解完了,咱们接下来正式介绍 ES的映射,ES是如何将索引文档和数据类型进行关联的,建立索引前是否必须制定索引文档的数据类型呢?
映射是定义一个文档及其包含的字段如何存储和索引的过程。例如,使用映射来定义:
其实在 ElasticSearch中能够不须要事先定义映射(Mapping),文档写入ElasticSearch时,会根据文档字段自动识别类型,可是经过这种自动识别的字段不是很精确,对于一些复杂的须要分词的就不适合了。
根据是否自动识别映射类型,咱们能够将映射分为动态映射和静态映射。
动态映射,即不事先指定映射类型(Mapping),文档写入ElasticSearch时,ES会根据文档字段自动识别类型,这种机制称之为动态映射。
静态映射,即人为事先定义好映射,包含文档的各个字段及其类型等,这种方式称之为静态映射,亦可称为显式映射。
Elasticsearch最重要的功能之一是它试图摆脱你的方式,让你尽快开始探索你的数据。Elasticsearch试图让你成功安装环境以后就能够直接使用。要索引文档,您没必要首先建立索引、定义映射类型和定义字段,其实您只需索引一个文档数据,而后索引、类型和字段将自动生效。
索引一个图书的文档:
PUT /library/book/1 { "bookId":1, "bookName":"Java核心技术 卷I", "publishDate":"2014-03-12" }
返回结果以下,表示成功
{ "_index": "library", "_type": "book", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 1, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
咱们看下mapping映射信息
GET library/_mapping
获得以下映射信息,重点关注mapping节点的内容
{ "library": { "mappings": { "book": { "properties": { "bookId": { "type": "long" }, "bookName": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "publishDate": { "type": "date" } } } } } }
能够看到,咱们并无建立索引映射,Elasticsearch自动根据文档数据为咱们映射了字段类型,bookId的映射类型为long,bookName的映射类型为多字段的即为text,同时也为keyword,publishDate的映射类型为date。能够看到ES的动态映射功能仍是蛮强大的。
默认状况下,当在文档中找到之前未见过的字段时,Elasticsearch会自动将这个新字段添加到类型映射中。咱们能够在文档和object级别禁用这项功能,具体操做方式就是经过将dynamic
参数设置为false
或strict
,设为false是忽略新字段,而设为strict是若是遇到未知字段,就抛出异常。
假设启用了动态字段映射功能,则使用一些简单的规则来肯定字段应具备的数据类型:
JSON datatype | Elasticsearch datatype |
---|---|
null | 没有字段添加 |
true or false | boolean |
integer | long |
object | object |
array | 依赖于数组中首个非空值 |
string | 能够是日期字段、double或long字段,也能够是带有关键字子字段的文本字段。 |
上面这些是能够动态检测到的字段数据类型,而其余的之外的字段必需要显式映射数据类型了。
对于string字符串字段,动态映射的结果会有多种,可能映射为日期类型,也可能映射为double或long类型,也可能映射为带有关键字的text类型,具体结果要看配置的检测类型,是日期检测仍是数字检测。
日期检测
若是date_detection
启用(默认),则检查新字符串字段以查看其内容是否与dynamic_date_formats
指定的任何日期模式匹配 。若是找到匹配项,那么则添加为具备对应格式的date新字段。
默认值为
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
获得的结果为:
{ "my_index": { "mappings": { "_doc": { "properties": { "city": { "type": "text", "fields": { "raw": { "type": "keyword" } } }, "create_date": { "type": "date", "format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis" } } } } } }
动态日期检测能够经过设置date_detection
为false
来禁用:
PUT my_index { "mappings": { "_doc": { "date_detection": false } } } PUT my_index/_doc/1 { "create": "2015/09/02" }
禁用以后,从新获取映射类型,获得以下结果:
{ "my_index": { "mappings": { "_doc": { "date_detection": false, "properties": { "create": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } } }
这时,create_date字段已被添加为文本字段。咱们也能够自定义检测到的日期格式,经过dynamic_date_formats
能够自定义以支持您本身的日期格式:
PUT my_index { "mappings":{ "_ doc":{ "dynamic_date_formats":["MM / dd / yyyy"] } } }
数字检测
虽然JSON支持本机浮点和整数数据类型,但某些应用程序或语言有时可能将数字呈现为字符串。一般,正确的解决方案是显式映射这些字段,但能够启用数字检测(默认状况下禁用)以自动执行此操做:
PUT my_index { "mappings":{ "_ doc":{ "numeric_detection":true } } } PUT my_index / _doc / 1 { "my_float":"1.0", "my_integer":"1" }
其中my_float字段将添加为float字段,my_integer字段将添加为long字段。
除了上面列出的选项外,还能够进一步自定义动态字段映射规则dynamic_templates
,动态模板容许您定义可应用于动态添加字段的自定义映射,具体取决于:
更多具体内容可参考官方文档,Dynamic templates一章这里就很少叙述了。
动态映射的自动类型推测功能并非100%正确的,这就须要静态映射机制。静态映射与关系数据库中建立表语句类型,须要事先指定字段类型。相对于动态映射,静态映射能够添加更加详细字段类型、更精准的配置信息等。
既然能够自定义映射字段类型,那么那些复杂的字段类型和分词器咱们均可以根据本身需求添加了,以提供了字段映射使用的各类映射参数的详细说明,这些映射参数对于某些或全部字段数据类型是通用的,内容太多,这里感兴趣的读者能够点击具体连接阅读。
映射参数 | 说明 |
---|---|
analyzer | 分析器 |
normalizer | 在 Elasticsearch 中处理字符串类型的数据时,若是咱们想把整个字符串做为一个完整的 term 存储,咱们一般会将其类型 type 设定为 keyword。但有时这种设定又会给咱们带来麻烦,好比同一个数据再写入时因为没有作好清洗,致使大小写不一致,好比 apple、Apple两个实际都是 apple,但当咱们去搜索 apple时却没法返回 Apple的文档。要解决这个问题,就须要 Normalizer出场了。 |
boost | 单个字段能够自动提高以计数更多的相关性得分 |
coerce | 强制尝试清除脏值以适合字段的数据类型。数据并不老是干净的,根据它的生成方式,数字可能会在JSON正文中呈现为真正的JSON数字,例如5,但它也可能呈现为字符串,例如"5"。或者,应该是整数的数字能够替代地呈现为浮点,例如5.0,或甚至 "5.0"。 |
copy_to | copy_to参数容许您建立自定义 _all字段,能够将多个字段的值复制到组字段中,而后能够将其做为单个字段进行查询。 |
doc_values | |
dynamic | 设置动态映射 |
enabled | enabled设置只能应用于映射类型和 object字段,致使Elasticsearch彻底跳过对字段内容的解析 |
fielddata | |
eager_global_ordinals | |
format | 格式化日期 |
ignore_above | |
ignore_malformed | |
index_options | |
index | |
fields | |
norms | |
null_value | 当字段设置为null,(或空数组或null值数组)时,它被视为该字段没有值。不能被索引或搜索 |
position_increment_gap | |
properties | |
search_analyzer | |
similarity | |
store | |
term_vector |