1. 对Mapping的理解

Mapping类似于关系型数据库的Schema,主要包含以下内容:

  1. 定义索引中字段的名称
  2. 定义字段的数据类型,如:字符串、数字、boolean等
  3. 可对字段设置倒排索引的相关配置,如是否需要分词,使用什么分词器

从7.x开始,一个Mapping只属于一个索引的type 默认type 为:_doc

  1. 每个文档属于一个type
  2. 一个type有且仅有一个Mapping定义
  3. 从7.x开始,不需要在Mapping中指定type信息,默认type为   _doc

2. Mapping的数据类型

ES 字段类型主要有:核心类型、复杂类型、地理类型以及特殊类型

2.1 核心类型

核心数据类型与我们常使用的强类型语言中的数据类型类似

  • text   用于全文索引,该类型的字段将通过分词器进行分词,最终用于构建索引
  • keyword    不分词
  • long    有符号64-bit integer:-2^63 ~ 2^63 - 1
  • integer    有符号32-bit integer,-2^31 ~ 2^31 - 1
  • short    有符号16-bit integer,-32768 ~ 32767
  • byte     有符号8-bit integer,-128 ~ 127
  • double    64-bit IEEE 754 浮点数
  • float    32-bit IEEE 754 浮点数
  • half_float    16-bit IEEE 754 浮点数
  • boolean    true,false
  • date    https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html
  • binary  该类型的字段把值当做经过 base64 编码的字符串,默认不存储,且不可搜索

2.1.1 字符串类型

在 ES 7.x 有两种字符串类型:text 和 keyword,在 ES 5.x 之后 string 类型已经不再支持了。

   text :类型适用于需要被全文检索的字段,例如新闻正文、邮件内容等比较长的文字,text 类型会被分词器(Analyzer)处理为一个个词项,并使用 Lucene 倒排索引存储,text 字段不能被用于排序,如果需要使用该类型的字段只需要在定义映射时指定 JSON 中对应字段的 type 为 text。

不会被分词,适合简短、结构化字符串,例如主机名、姓名、商品名称等,可以用于过滤、排序、聚合检索,也可以用于精确查询。

2.1.2 日期类型

格式化的日期字符串,例如 2020-03-17 00:00、2020/03/17时间戳(和 1970-01-01 00:00:00 UTC 的差值),单位毫秒或者秒即使是格式化的日期字符串,ES 底层依然采用的是时间戳的形式存储

{
  "mappings": {
    "_doc": {
      "properties": {
        "create_date": {
          "type": "date", 
          "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
        }
      }
    }
  }
}

JSON 文档中同样存在布尔类型,不过 JSON 字符串类型也可以被 ES 转换为布尔类型存储,前提是字符串的取值为 true 或者 false,布尔类型常用于检索中的过滤条件。

二进制类型 binary 接受 BASE64 编码的字符串,默认 store 属性为 false,并且不可以被搜索。

范围类型可以用来表达一个数据的区间,可以分为5种:

integer_range、float_range、long_range、double_range 以及 date_range。

2.2、复杂类型

    复合类型主要有对象类型(object)嵌套类型(nested)

2.2.1、对象类型(object)

      JSON 字符串允许嵌套对象,一个文档可以嵌套多个、多层对象。可以通过对象类型来存储二级文档,不过由于 Lucene 并没有内部对象的概念,ES 会将原 JSON 文档扁平化,例如文档:

PUT my_index/_doc/1
{ 
  "region": "US",
  "manager": { 
    "age":     30,
    "name": { 
      "first": "John",
      "last":  "Smith"
    }
  }
}

 自动生成的mapping如下:

{
  "mapping": {
    "properties": {
      "manager": {
        "properties": {
          "age": {
            "type": "long"
          },
          "name": {
            "properties": {
              "first": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "last": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              }
            }
          }
        }
      },      
      "region": {
        "type": "text",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }      
    }
  }
}

其中域manager就是一个对象类型,其中的name是它的子对象。对于对象类型,缺省设置“type”为”object”,因此不用显式定义“type”。
  对于对象类型,ES在索引时将其转换为"manager.age", "manager.name.first" 这样扁平的key,因此查询时也可以使用这样的扁平key作为域来进行查询。

2.2.2 嵌套类型(nested)

嵌套类型可以看成是一个特殊的对象类型,可以让对象数组独立检索,例如文档

"user" : [ 
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]

自动映射如下:

"user.first" : [ "alice", "john" ],
"user.last" :  [ "smith", "white" ]

此时,需要设置为:

"user": {
          "type": "nested" 
        }

 2.3. 地理数据类型

geo_point类型:可用于存储某个地理坐标的经纬度。

// location为geo_point类型
"location": { 
    "lat": 41.12,
    "lon": -71.34
  }

geo_shape类型:用于存储地理多边形形状 

2.4. 特殊数据类型

  • ip类型:用于表示IPv4与IPv6的地址
  • completion类型:提供自动输入关联完成功能,如常见的baidu搜索框。
  • token_count类型:用于计算字符串token的长度,使用时需提供"analyzer"定义。
  • percolate类型:定义为percolate类型的字段会被ES分析为一个查询并保存下来,并可用在后继对文档的查询中。Percolate可以理解为一个预置的查询。
  • alias类型:定义一个已存在域的别名。
  • join类型:该类型定义了文档对象之间的父子关系(可定义多层,形成一颗层次树),即同一索引中多个文档对象可以存在依赖关系,如互联网应用常见的博客文章与回复,问题与回答之间的关系。

2.5.数组类型

elasticsearch不提供专门的数组类型。但任何字段,都可以包含多个相同类型的数值。

# 数组类型
PUT users/_doc/1
{
  "name":"onebird",
  "interests":"reading"
}
 
PUT users/_doc/1
{
  "name":"twobirds",
  "interests":["reading","music"]
}
 
POST users/_search
{
  "query": {
        "match_all": {}
    }
}
 
# interests字段还是text类型
GET users/_mapping

3. Dynamic Mapping

  1. 在写入文档时,如果索引不存在,会自动创建索引
  2. 这种机制,使得我们无需手动定义mappings。Elasticsearch会自动根据文档信息,推算出字段的类型
  3. 有的时候,Elasticsearch可能会推算不对,如:地理位置信息
  4. 当类型推算得不对时,可能导致一些功能无法正常运行,如Range查询。

3.1、类型自动识别

     ES 类型的自动识别是基于 JSON 的格式,如果输入的是 JSON 是字符串且格式为日期格式,ES 会自动设置成 Date 类型;当输入的字符串是数字的时候,ES 默认会当成字符串来处理,可以通过设置来转换成合适的类型;如果输入的是 Text 字段的时候,ES 会自动增加 keyword 子字段

 3.2 能否更改mapping的字段类型

1、新增加的字段

  • dynamic设为true时,新增字段的文档写入时,Mapping同时被更新
  • dynamic设为false时,Mapping不会被更新,新增字段的数据无法被索引,但是会出现在_source中
  • dynamic设为strict,文档将写入失败

 2、已存在的字段,一旦数据被写入,就不再支持修改字段定义

  • Lucene本身的限制
  • 如果希望更改字段类型,必须Reindex api,即:重建索引。在数据量多的时候,开销将非常大
# dynamic设置为false
PUT idx1
{
    "mapping": {
        "_doc": {
            "dynamic": "false"
        }
    }
}
 
# 修改为dynamic为false
PUT idx1/_mapping
{
  "dynamic": false
}
 
# 查看索引
GET idx1/_mapping

4. 显式Mapping及常见参数

mappings 中field定义选择

"field": {  
         "type":  "text", //文本类型
       
         "index": "false"// ,设置成false,字段将不会被索引  
         
         "analyzer":"ik"//指定分词器  
         
         "boost":1.23//字段级别的分数加权  
         
         "doc_values":false//对not_analyzed字段,默认都是开启,analyzed字段不能使用,对排序和聚合能提升较大性能,节约内存,如果您确定不需要对字段进行排序或聚合,或者从script访问字段值,则可以禁用doc值以节省磁盘空间:
         
         "fielddata":{"loading" : "eager" }//Elasticsearch 加载内存 fielddata 的默认行为是 延迟 加载 。 当 Elasticsearch 第一次查询某个字段时,它将会完整加载这个字段所有 Segment 中的倒排索引到内存中,以便于以后的查询能够获取更好的性能。
         
         "fields":{"keyword": {"type": "keyword","ignore_above": 256}} //可以对一个字段提供多种索引模式,同一个字段的值,一个分词,一个不分词  
         
         "ignore_above":100 //超过100个字符的文本,将会被忽略,不被索引
           
         "include_in_all":ture//设置是否此字段包含在_all字段中,默认是true,除非index设置成no选项  
         
         "index_options":"docs"//4个可选参数docs(索引文档号) ,freqs(文档号+词频),positions(文档号+词频+位置,通常用来距离查询),offsets(文档号+词频+位置+偏移量,通常被使用在高亮字段)分词字段默认是position,其他的默认是docs  
         
         "norms":{"enable":true,"loading":"lazy"}//分词字段默认配置,不分词字段:默认{"enable":false},存储长度因子和索引时boost,建议对需要参与评分字段使用 ,会额外增加内存消耗量  
         
         "null_value":"NULL"//设置一些缺失字段的初始化值,只有string可以使用,分词字段的null值也会被分词  
         
         "position_increament_gap":0//影响距离查询或近似查询,可以设置在多值字段的数据上火分词字段上,查询时可指定slop间隔,默认值是100  
         
         "store":false//是否单独设置此字段的是否存储而从_source字段中分离,默认是false,只能搜索,不能获取值  
         
         "search_analyzer":"ik"//设置搜索时的分词器,默认跟ananlyzer是一致的,比如index时用standard+ngram,搜索时用standard用来完成自动提示功能  
         
         "similarity":"BM25"//默认是TF/IDF算法,指定一个字段评分策略,仅仅对字符串型和分词类型有效  
         
     "term_vector":"no"//默认不存储向量信息,支持参数yes(term存储),with_positions(term+位置),with_offsets(term+偏移量),with_positions_offsets(term+位置+偏移量) 对快速高亮fast vector highlighter能提升性能,但开启又会加大索引体积,不适合大数据量用  
       }

1. type字段类型

字段的数据类型。

2. index

可用于设置字段是否被索引,默认为true,false即为不可搜索

3. analyzer

添加数据时,需要分词的数据使用该分词器分词后建立索引。

比如ik分词器。

4. boost

字段级别的分数加权

5. doc_values

对not_analyzed字段,默认都是开启,analyzed字段不能使用,对排序和聚合能提升较大性能,节约内存,如果您确定不需要对字段进行排序或聚合,或者从script访问字段值,则可以禁用doc值以节省磁盘空间:

6. fielddata

Elasticsearch 加载内存 fielddata 的默认行为是 延迟 加载 。 当 Elasticsearch 第一次查询某个字段时,它将会完整加载这个字段所有 Segment 中的倒排索引到内存中,以便于以后的查询能够获取更好的性能。

7. fields

可以对一个字段提供多种索引模式,同一个字段的值,一个分词,一个不分词

8. ignore_above

超过100个字符的文本,将会被忽略,不被索引

9. include_in_all

设置是否此字段包含在_all字段中,默认是true,除非index设置成no选项。

10. index_options

4个可选参数docs(索引文档号) ,freqs(文档号+词频),positions(文档号+词频+位置,通常用来距离查询),offsets(文档号+词频+位置+偏移量,通常被使用在高亮字段)分词字段默认是position,其他的默认是docs

11. norms

分词字段默认配置,不分词字段:默认{"enable":false},存储长度因子和索引时boost,建议对需要参与评分字段使用 ,会额外增加内存消耗量

12. null_value

设置一些缺失字段的初始化值,只有string可以使用,分词字段的null值也会被分词

 需要对Null值实现搜索时使用。只有keyword类型才支持设定null_value

13. position_increament_gap

影响距离查询或近似查询,可以设置在多值字段的数据的分词字段上,查询时可指定slop间隔,默认值是100

14. store

是否单独设置此字段的是否存储而从_source字段中分离,默认是false,只能搜索,不能获取值

15. search_analyzer

搜索分词器,搜索条件需要分词的时候,使用该分词器。

16. similarity

默认是TF/IDF算法,指定一个字段评分策略,仅仅对字符串型和分词类型有效

17. term_vector

默认不存储向量信息,支持参数yes(term存储),with_positions(term+位置),with_offsets(term+偏移量),with_positions_offsets(term+位置+偏移量) 对快速高亮fast vector highlighter能提升性能,但开启又会加大索引体积,不适合大数据量用;

18. format

设置数据格式,用于日期类型。

19. copy_to

当前值域拷贝到另一个域。

20. dynamic

控制字段的新增。

21. coerced 

值为false时,强制数据类型一致;

官网参考文档:Mapping parameters | Elasticsearch Guide [6.8] | Elastic