1.什么是Mapping
1.Mapping 类似数据库中的schema的定义,作用如下
- 定义索引中的字段的名称
- 定义字段的数据类型,例如字符串,数字,布尔…
- 字段,倒排索引的相关配置(Analyzed or Not Analyzed,Analyzer)
2.Mapping会把JSON文档映射成Lucene所需要的扁平格式
3.一个Mapping属于一个索引的Type
- 每个文档都属于一个Type
- 一个Type有一个Mapping定义
- 7.0开始不需要在Mapping定义中指定type信息
1.1 字段的数据类型
- 简单类型
- Text/Keyword
- Date
- Integer/Floating
- Boolean
- IPv4 & IPv6
- 复杂类型-对象和嵌套对象
- 对象类型/嵌套类型
- 特殊类型
- geo_point & geo_shape / percolator
2 什么是Dynamic Mapping
-
在写入文档时候,如果索引不存在,会自动创建索引
-
Dynamic Mapping的机制,使得我们无需手动定义Mappings. Elasticsearch 会自动根据文档信息,推算出字段的类型
-
但是有时候会推算的不对,例如地理位置信息推算成text
-
当类型如果设置不对时,会导致一些功能无法正常运行,例如Range查询
//写入文档,查看 Mapping PUT mapping_test/_doc/1 { "firstName":"Chan", "lastName": "Jackie", "loginDate":"2018-07-24T10:29:48.103Z" } // 查看mapping GET mapping_test/_mapping // 返回结果 { "mapping_test" : { "mappings" : { "properties" : { "firstName" : { "type" : "text", // 类型 每一个 text 都有 keyword "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "lastName" : { "type" : "text", //类型 "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } }, "loginDate" : { "type" : "date" //日期类型 } } } } } DELETE mapping_test
2.1 类型的自动识别
JSON类型 | Elasticsearch类型 |
---|---|
字符串 | 匹配日期格式,设置成Date |
字符串 | 配置数字设置为float或者long,该选项默认关闭 |
字符串 | 设置为Text ,并且增加keyword子字段 |
布尔值 | boolean |
浮点数 | float |
整数 | long |
对象 | Object |
数组 | 由第一个非空数值的类型所决定 |
空值 | 忽略 |
//dynamic mapping,推断字段的类型
PUT mapping_test/_doc/1
{
"uid" : "123",
"isVip" : false,
"isAdmin": "true",
"age":19,
"heigh":180
}
GET mapping_test/_mapping
# 返回结果
{
"mapping_test" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"heigh" : {
"type" : "long"
},
"isAdmin" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"isVip" : {
"type" : "boolean"
},
"uid" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
2.2 能否更改Mapping的字段类型
两种情况
- 新增加字段
- Dynamic 设为true时,一旦有新增字段的文档写入,Mapping也同时被更新
- Dynamic 设为false,Mapping不会被更新,新增字段的数据无法被索引
- Dynamic 设置成Strict ,文档写入失败
- 对已有字段,一旦已经有数据写入,就不再支持修改字段定义
- Lucene 实现的倒排索引,一旦生成后,就不允许修改
- 如果希望改变字段类型,必须 Reindex API 重建索引
- 如果修改了字段的数据类型,会导致已被索引的属于无法被搜索
- 但是如果是增加了新的字段,就不会有这样的影响
2.3 控制Dynamic Mappings
-
当dynamic 被设置成false时候,存在新增字段的数据写入,该数据可以被索引,但是新增字段被丢弃
-
当设置成Strict模式时候,数据直接写入直接出错
//默认Mapping支持dynamic,写入的文档中加入新的字段 PUT dynamic_mapping_test/_doc/1 { "newField":"someValue" } //该字段可以被搜索,数据也在_source中出现 POST dynamic_mapping_test/_search { "query":{ "match":{ "newField":"someValue" } } } //修改为dynamic false PUT dynamic_mapping_test/_mapping { "dynamic": false } //新增 anotherField PUT dynamic_mapping_test/_doc/10 { "anotherField":"someValue" } //该字段不可以被搜索,应为dynamic已经被设置为false POST dynamic_mapping_test/_search { "query":{ "match":{ "anotherField":"someValue" } } } get dynamic_mapping_test/_doc/10 //修改为strict PUT dynamic_mapping_test/_mapping { "dynamic": "strict" } //写入数据出错,HTTP Code 400 PUT dynamic_mapping_test/_doc/12 { "lastField":"value" } DELETE dynamic_mapping_test
3 显示定义一个Mapping
一些建议
3.1 Index
Index 控制当前字段是否被索引,默认是true,如果设置为false,该字段不可被索引
设置索引
PUT users
{
"mappings" : {
"properties" : {
"firstName" : {
"type" : "text"
},
"lastName" : {
"type" : "text"
},
"mobile" : {
"type" : "text",
"index": false // 设置mobile 字段不可被索引
}
}
}
}
插入数据
PUT users/_doc/1
{
"firstName":"Ruan",
"lastName": "Yiming",
"mobile": "12345678"
}
搜索字段
POST /users/_search
{
"query": {
"match": {
"mobile":"12345678"
}
}
}
返回结果
"error": {
"root_cause": [
{
"type": "query_shard_exception",
"reason": "failed to create query:
3.2 Index Options
- 四种不同级别的Index Options 配置,可以控制倒排索引记录的内容
- docs --记录 doc id
- freqs – 记录 doc id , term frequencies
- posititions --记录 doc id ,term frequencies, term position
- offsets --记录 doc id,term frequencies,term posistion,character offects
- Text 类型默认记录 positions,其他默认为docs
- 记录内容越多,占用空间越大
定义mapping
PUT my_index
{
"mappings": {
"properties": {
"text": {
"type": "text",
"index_options": "offsets"
}
}
}
}
插入数据
PUT /my_index/_doc/1
{
"text": "Quick brown fox"
}
search
GET /my_index/_search'
{
"query": {
"match": {
"text": "brown fox"
}
},
"highlight": {
"fields": {
"text": {}
}
}
}
3.3 null_value
一个字段是null值则不能被索引或搜索。当字段设置为null(或空数组)时,它被视为该字段没有值。
null_value参数允许您使用指定的值替换null,以便可以对其进行索引和搜索
定义mapping
DELETE users
PUT users
{
"mappings" : {
"properties" : {
"firstName" : {
"type" : "text"
},
"lastName" : {
"type" : "text"
},
"mobile" : {
"type" : "keyword",
"null_value": "NULL_test"
}
}
}
}
插入值
PUT users/_doc/1
{
"firstName":"Ruan",
"lastName": "Yiming",
"mobile": null
}
PUT users/_doc/2
{
"firstName":"Ruan2",
"lastName": "Yiming2"
搜索
}
GET users/_search
{
"query": {
"match": {
"mobile":"NULL_test"
}
}
}
返回值
{
"took" : 25,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "users",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.2876821,
"_source" : {
"firstName" : "Ruan",
"lastName" : "Yiming",
"mobile" : null // 可以被索引 但是id=2的没有不能被搜索到
}
}
]
}
}
3.4 copy_to
copy_to将字段的数值拷贝到目标字段,实现类似 _all的作用
copy_to的目标字段不出现在_source中,可以满足一些特定的搜索需求
定义mapping
DELETE users
PUT users
{
"mappings": {
"properties": {
"firstName":{
"type": "text",
"copy_to": "fullName"
},
"lastName":{
"type": "text",
"copy_to": "fullName"
}
}
}
}
插入值
PUT users/_doc/1
{
"firstName":"Ruan",
"lastName": "Yiming"
}
搜索
GET users/_search?q=fullName:(Ruan Yiming)
POST users/_search
{
"query": {
"match": {
"fullName":{
"query": "Ruan Yiming",
"operator": "and"
}
}
}
}
返回结果
{
"took" : 16,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "users",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5753642,
"_source" : {
"firstName" : "Ruan",
"lastName" : "Yiming"
}
}
]
}
}
更多的参数请参考
Elasticsearch
4 数组类型
Elasticsearch 中不提供专门的数组类型。但是任何字段,都可以包含多个相同多个相同类类型的数值
//数组类型
PUT users/_doc/1
{
"name":"onebird",
"interests":"reading"
}
PUT users/_doc/1
{
"name":"twobirds",
"interests":["reading","music"]
}
POST users/_search
{
"query": {
"match_all": {}
}
}
GET users/_mapping