ElasticSearch 的Mapping 和常见字段类型
-
什么是 Mapping
- Mapping 类似数据库中的 schema 的定义,作用如下:
- 定义索引中的字段名称
- 定义字段的数据类型,如 字符串,数字,布尔…
- 字段、倒排索引的相关配置 (分不分词,分词器的选择等)
- Mapping 会把 JSON 文档映射成 Lucene 所需要的扁平格式
- 一个Mapping属于一个索引的 Type
- 每个文档都属于一个Type
- 一个 Type 有同一个 Mapping 定义
- 7.0 开始,不需要在 Mapping 定义中指定 type 信息
- Mapping 类似数据库中的 schema 的定义,作用如下:
-
字段的数据类型
- 简单类型
- Text / Keyword
- Date
- Integer / Floating
- Boolean
- IPv4 & IPv6
- 复杂类型 - 对象和嵌套对象
- 对象类型 / 嵌套类型
- 特殊类型
- geo_point & geo_shape / percolator 地理信息
- 简单类型
-
什么是 Dynamic Mapping
- 在写入文档的时候,如果索引不存在,会自动创建索引
- Dynamic Mapping 的机制,使得我们可以无需手动定义 Mappings,ElasticSearch 会自动根据文档信息,推算出字段的类型,但是有时候会推算得不准
- 当类型设置不对时,会导致一些功能无法正常运行,例如 Range 查询
-
ElasticSearch 类型的自动识别
ElasticSearch 类型的自动识别是基于 JSON 的格式的
JSON 类型 ElasticSearch 类型 字符串 - 匹配日期格式,设置成 Date
- 匹配数字设置为float
或 long ,该选项默认关闭
- 设置为 Text ,并且增加 keyword 子字段布尔值 boolean 浮点数 float 整数 long 对象 Object 数组 由第一个非空数值的类型所决定 空值 忽略 -
能否更改 Mapping 的字段类型
-
新增字段
- Dynamic 设为 true 时,有新增的字段写入, Mapping 也同时会更新
- Dynamic 设为 false 时,Mapping 不会被更新,新增字段的数据无法被索引,但是字段信息会出现在 _source 中
- Dynamic 设为 Strict ,文档写入失败
-
对已有字段,一旦已经有数据写入,就不在支持修改字段定义
- Lucene 实现的倒排索引,一旦生成后,就不允许修改
-
如果希望改变字段类型,必须 Reindex API ,重建索引
-
原因:
- 如果修改了字段的数据类型,会导致已被索引的数据无法被搜索
- 如果是新增的字段,就不会有这样的影响
-
控制 Dynamic Mappings
true false strict 文档可索引 ✅ ✅ ❌ 字段可更新 ✅ ❌ ❌ Mapping 被更新 ✅ ❌ ❌ - 当 dynamic 被设置成 false 时,新增字段数据,该数据可以存入es,但是该字段不能被搜索,mapping也不会更新
- 当设置成 Strict 模式时,数据写入直接出错
修改 dynamic 方法
PUT movies/_mapping { "dynamic":true }
-
显式 Mapping 的设置及常见参数介绍
如何显式定义一个 Mapping
PUT movies
{
"mappings":{
// 定义内容
}
}
自定义 Mapping 的一些建议
- 可以参考 API 手册,纯手写
- 可以为了减少输入的工作量,减少出错概率,可以依照以下步骤
- 创建一个临时的 index ,写入一些样本数据
- 通过访问 Mapping API 获取该 index 的动态 Mapping 定义
- 修改后复制 JSON 定义,使用该配置创建索引
- 删除临时索引
控制当前字段是否被索引
index
控制当前字段是否被索引。默认为 true 。
如果设置成 false,该字段不可被搜索
但是用其他字段搜索,该字段可见
PUT users
{
"mappings":{
"properties":{
"firstName":{
"type":"text"
},
"lastName":{
"type":"text"
},
"mobile":{
"type":"text",
"index":false # 该字段不可被搜索
}
}
}
}
Index Options
- 有四种级别的 Index Options 配置,可以控制倒排索引记录的内容
- docs :记录 doc id
- freqs :记录 doc id 和 term frequencies
- positions :记录 doc id 、term frequencies 、 term position
- offsets : 记录 doc id 、term frequencies 、 term position 、character offects
- Text 类型默认记录 postions ,其他默认为 docs
- 记录内容越多 ,占存储空间越大
null_value
有时候插入的某些字段值为 NULL
,但是又需要对 NULL
值进行搜索,可以使用 null_value,把 NULL
定义为一个指定的字符串,如 “NULL”
PUT users
{
"mappings":{
"properties":{
"firstName":{
"type":"text"
},
"lastName":{
"type":"text"
},
"mobile":{
"type":"keyword", # 只有Keyword 类型支持设定 Null_value
"null_value":"NULL"
}
}
}
}
copy_to 设置
- copy_to 将字段的值拷贝到目标字段
- copy_to 的目标字段不出现在 _source 中
- 用来满足一些特定的搜索需求
PUT users
{
"mappings":{
"properties":{
"firstName":{
"type":"text",
"copy_to":"fullName"
},
"lastName":{
"type":"text",
"copy_to": "fullName"
}
}
}
}
GET users/_search?q=fullName:(Z hl)
数组类型
ElasticSearch 中不提供专门的数组类型,但是任何字段,都可以包含多个相同类型的值
POST users/_doc
{
"firstName":"Jack2",
"lastName":"Jonson2"
}
POST users/_doc
{
"firstName":["Jack2","jjj"],
"lastName":"Jonson2"
}
多字段类型
- 多字段特性
- 增加一个 keyword 字段,实现字段名精确匹配
- 使用不同的 analyzer
- 不同的语言
- 使用拼音对字段进行搜索
- 还支持为搜索和索引指定不同的 analyzer
PUT products
{
"mappings": {
"properties": {
"commpany": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256 # 对超过256的字符串,analyzer不会进行处理
}
}
},
"comment": {
"type": "text",
"fields": {
"english_comment": {
"type": "text",
"analyzer": "english",
"search_analyzer": "english"
}
}
}
}
}
}
精确值和全文本的比较
Exact Values
v.s Full Text
-
Exact Values
精确值:包括 数字、日期、具体的字符串-
ElasticSearch 里的 keyword 就是精确值
-
精确值不需要被分词
-
-
Full Text
全文本,非结构化的文本数据ElasticSearch 里的 text 就是全文本
Index Template 和 Dynamic Template
什么是 Index Template
- Index Templates : 帮你设定 Mappings 和 Settings,并按照一定的规则,自动匹配到新创建的索引之上
- 模板仅在一个索引被新创建时,才会产生作用。修改模板不会影响已创建的索引
- 你可以设定多个索引模块,这些设置会被 “merge” 在一起
- 你可以指定 “order” 的数值,控制 “merging” 的过程
PUT _template/template_test
{
"index_patterns": ["test*"], # 作用在以test开头的索引
"order":1,
"settings": {
"number_of_replicas": 1,
"number_of_shards": 2
},
"mappings": {
"date_detection": false, # 关闭字符串自动转日期
"numeric_detection": true # 开启字符串自动转数字
}
}
Index Template 的工作方式
当一个索引被新创建时:
- 应用 ElasticSearch 默认的 settings 和 mappings
- 应用 order 数值低的 Index Template 中的设定
- 应用 order 数值高的 Index Template 中的设定,会覆盖之前的设定
- 应用用户创建时所指定的 Settings 和 Mappings ,并覆盖之前模板中的设定
什么是 Dynamic Template
Dynamic Template 是设定在一个具体的 index 上的,根据 ElasticSearch 识别的数据类型,结合字段名称,来动态设定字段类型,如:
- 所有的字符串类型都设定成 Keyword ,或者关闭 keyword
- is 开头的字段都设置成 boolean
- long_ 开头的都设置成 long 类型
PUT my_test_index
{
"mappings": {
"dynamic_templates":[
{
"string_as_boolean":{
"match_mapping_type":"string",
"match":"is*",
"mapping":{
"type":"boolean"
}
}
},
{
"string_as_keywords":{
"match_mapping_type":"string",
"mapping":{
"type":"keyword"
}
}
}
]
}
}
- Dynamic Template 是定义在某个索引的 Mappings中的
- Template 有一个名称
- 匹配规则是一个数组
- 为匹配到字段设置 Mappings