一. mappings(映射)是什么
es中,有Index(索引),Type(类型,6.x以后一个Index只能拥有一个Type),Document(文档,单行记录),Field(字段,单个文档中的单个字段)这几项组成一条记录。然后,一个Document(文档),包含哪些Field(字段),每个Field(字段)是什么数据类型,采用什么分词机制(例如:中文语句用中文分词机制,英文语句用英文分词机制),这些元数据信息,都是写在mapping中的。
es存在动态映射,即不用预先定义字段,字段类型的mapping信息,当PUT一条记录到es的某个Index的某个Type中时,ES自动分析每个字段的值,配合一些默认设置(例如分词机制,分词最大长度),自动生成出对应的mapping内容。当然,很多时候默认的不会完全符合应用场景,也可能会造成一些不必要的浪费,所以,我们需要研究mapping的组成和功能。
二.mapping怎么查询
//创建空的Index
PUT maptest
{}
//查看mapping信息
GET /maptest/_mapping
显示结果如下:
{
"maptest": { //索引名
"mappings": {} //mapping信息,没有字段的时候为null,这时候es读取mapping时,使用es默认值。
}
}
动态映射测试
首先不设置mapping信息,put一条记录到maptest中,es会自动生成对应的mapping信息。
PUT maptest/type/1
{"name":"张三"}
查看动态生成的mapping信息。
{
"maptest": { //索引名
"mappings": { //mappings信息
"type": { //type名 6.0以后一个索引只能有一个type
"properties": { //properties存放的是field信息
"name": { //字段name
"type": "text", //name的数据类型 [1]
"fields": { //multi-fields [2]
"keyword": { //multi-fields 的字段名,keyword
"type": "keyword", // keyword的数据类型 keyword
"ignore_above": 256 // keyword忽略长度 [3]
}
}
}
}
}
}
}
}
[1]:es支持的数据类型种类 详情参考 ElasticSearch 6.x 学习笔记:12.字段类型
[2]: multi-fields 多域,ES提供的特殊功能,可以让一个字段,同时拥有多个数据类型,原理是存放一个其他数据类型的副本,如上图,name字段是 text类型的,text在es中,存储数据的时候,会自动分词,并生成索引,text无法进行排序,聚合,无法按照精准匹配搜索到结果,keyword支持精准匹配,排序,聚合,但是不支持分词,即关键字检索。所以,mapping自动生成了一个name.keyword多域字段,类型为keyword,这样,name支持分词,name.keyword支持精确匹配,让name同时支持精确匹配和模糊匹配
[3]: keyword类型是将整个文本作为一个词进行匹配,所以当这个词的长度很长时,精确匹配的效率会降低,所以,设置ignore_above长度,超过256字符的keyword文本将无法进行检索(该文本依然会保存,但是无法检索到)。
三. 手动设置mapping
3.1 dynamic-mapping的动态映射参数
mapping的动态映射开关可以设置
POST /maptest/type/_mapping
{
"maptest": {
"mappings": {
"type": {
"dynamic":"true", //动态映射开关
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
在type的下面,可以设置dynamic参数,开关maptest的动态映射。
dynamic属性:
- dynamic设置为ture:默认值,新增加的字段被添加到索引映射中;
- dynamic设置为false:新增加的字段会被忽略,字段数据会写入,但是mapping中找不到该字段的properties,并且无法检索;
- dynamic设置为strict:当向文档中新增字段时,ElasticSearch引擎抛出异常;
下面展示一下false的情况,首先关闭dynamic动态映射,put一个新的字段到mapping中,
//修改mapping dynamic为 false
PUT /maptest/type/_mapping
{
"type": {
"dynamic":false
}
}
// 插入age数据
PUT maptest/type/2
{
"age":"13"
}
//查询全部数据
GET maptest/_search
{
"query": {
"match_all": {}
}
}
查询结果中,age存在
{
"took": 5,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "maptest",
"_type": "type",
"_id": "2",
"_score": 1,
"_source": {
"age": "13" // age存在 数据未丢失
}
},
{
"_index": "maptest",
"_type": "type",
"_id": "1",
"_score": 1,
"_source": {
"name": "张三"
}
}
]
}
}
查看mapping,发现age字段没有自动生成映射,无法按age进行数据检索。
{
"maptest": {
"mappings": {
"type": {
"dynamic": "false",
"properties": {
"name": { //只有name字段,age字段没有生成mapping
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}
如果改成strict模式,然后插入address:"中国"的数据,在查看结果
PUT /maptest/type/_mapping
{
"type": {
"dynamic":"strict"
}
}
// strict模式下,插入mapping中不存在的字段报错,age字段因为已经存在于数据中,没有报错。
PUT maptest/type/3
{
"address":"中国"
}
{
"error": {
"root_cause": [
{
"type": "strict_dynamic_mapping_exception",
"reason": "mapping set to strict, dynamic introduction of [address] within [type] is not allowed"
}
],
"type": "strict_dynamic_mapping_exception",
"reason": "mapping set to strict, dynamic introduction of [address] within [type] is not allowed"
},
"status": 400
}
3.2 dynamic_date_formats- es date类型识别格式
PUT /maptest/type/_mapping
{
"type": {
"dynamic":"true", // 设置自动映射开始
"date_detection":true, // 开启日期转换,默认为true
"dynamic_date_formats":["yyyy-MM-dd hh:mm:ss", "yyyy-MM-dd" ] //日期转换的格式
}
}
// 自动映射
PUT maptest/type/4
{
"sdate":"2018-11-12"
}
date_detection : 日期检测开关,默认为true,false时关闭
当字段数据为字符串时,如果通过了日期格式检测,则字段类型识别为date类型,默认的日期格式检测为
[ "strict_date_optional_time","yyyy/MM/dd HH:mm:ss || yyyy/MM/dd"]
格式识别可以通过 dynamic_date_formats参数修改
"dynamic_date_formats":["yyyy-MM-dd hh:mm:ss", "yyyy-MM-dd" ]
四.字段属性
这一段可以查阅博客 Elasticsearch整理之mapping的参数,博主对es官方文档进行了详细翻译。
查阅ES官方文档点击这里Mapping parameters
属性名 | 说明 | 默认值 |
analyzer | 分词器名称 | standard标准分词器 |
normalizer | 统一处理方法,例如将Apple,apple,applE,统一按lowercase处理,检索时全部都能检索到 | 无 |
boost | 字段级别的助推,默认值是1,定义了字段在文档中的重要性/权重 | 1 |
coerce | 尝试将字符串转换为数值,如果字段类型是整数,那么将小数取整 | true |
copy_to | 该属性指定一个字段名称,ElasticSearch引擎将当前字段的值复制到该属性指定的字段中 | 无 |
doc_values | 文档值是存储在硬盘上的索引时(indexing time)数据结构,对于index:"not_analyzed"字段,默认值是true,analyzed string字段不支持文档值; | |
dynamic | 能够动态的增加自动,可对index,单个对象设置 | true |
enabled | 搜索开关,设置为false后,保存数据但是不可检索 | true |
fielddata | 字段数据是存储在内存中的查询时(querying time)数据结构,只支持analyzed string字段 | |
eager_global_ordinals | 按照global ordinals积极把fielddata加载到内存 | true |
format | 指定日期的格式,例如:“yyyy-MM-dd hh:mm:ss” | |
ignore_above | 该属性值指的是字符数量,而不是字节数量;超过长度后,后面的字符将会被分析器忽略。 | 256 |
ignore_malformed | 忽略格式错误的数值,默认值是false,不忽略错误格式,对整个文档不处理,并且抛出异常 | false |
index_options | index_options指出哪些信息被加到倒排索引中,docs,freqs,positions,offsets,stored文档默认为positions,其他文档默认为docs | |
index | 该属性控制字段是否编入索引被搜索,可以设置为true,false | true |
fields | 多域,一个字段使用多种其他类型的副本数据,满足不同的搜索场景 | |
norms | 用于标准化文档,以便查询时计算文档的相关性。建议不开启 默认不开启 | false |
null_value | 默认情况下值为null的字段不被index和search,该参数可以让值为null的字段变得可index和search | |
position_increment_gap | 多字段位置相邻度 | |
properties | 嵌套字段,对象的字段信息。 | |
search_analyzer | 搜索时使用的分析器,默认情况下,查询将使用analyzer字段制定的分析器,但也可以被search_analyzer覆盖 | |
similarity | 指定文档的评分模型,参数由"BM25"(默认), "classic"(TF/IDF), "boolean"(布尔评分模型) | |
store | 指定是否将字段的原始值写入索引,默认值是no,字段值被分析,能够被搜索,但是,字段值不会存储,这意味着,该字段能够被查询,但是不会存储字段的原始值。 | no |
term_vector | 词条向量 |
详细解释
4.1 properties-对象类型和嵌套对象属性
ES支持对象数据类型,可以把json识别为嵌套对象,同时,mapping的字段信息中会存在一个properties属性
PUT maptest/type/6
{
"user":{ //user是一个json对象,es会自动映射
"id":"123",
"time":"2018-11-12"
}
}
mapping的结构如下
{
"maptest": {
"mappings": {
"type": {
"dynamic": "true",
"dynamic_date_formats": [
"yyyy-MM-dd hh:mm:ss",
"yyyy-MM-dd"
],
"date_detection": true,
"properties": { // 第一层properties,type的字段信息
"user": { //user是一个字段
"properties": { //嵌套对象 第二层properties
"id": { //user.id
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"time": { //user.time
"type": "date",
"format": "yyyy-MM-dd"
}
}
}
}
}
}
}
}
同时,user.id,user.time是可以检索的
4.2 index-字段检索开关
index: 该属性控制字段是否编入索引被搜索,该属性可以设置为:true,false,默认为true