文章目录

  • ElasticSearch 的Mapping 和常见字段类型
  • 什么是 Mapping
  • 字段的数据类型
  • 什么是 Dynamic Mapping
  • ElasticSearch 类型的自动识别
  • 能否更改 Mapping 的字段类型
  • 显式 Mapping 的设置及常见参数介绍
  • 如何显式定义一个 Mapping
  • 自定义 Mapping 的一些建议
  • 控制当前字段是否被索引
  • Index Options
  • null_value
  • copy_to 设置
  • 数组类型
  • 多字段类型
  • 精确值和全文本的比较
  • Index Template 和 Dynamic Template
  • 什么是 Index Template
  • Index Template 的工作方式
  • 什么是 Dynamic Template


ElasticSearch 的Mapping 和常见字段类型

什么是 Mapping

  • Mapping 类似数据库中的 schema 的定义,作用如下:
  • 定义索引中的字段名称
  • 定义字段的数据类型,如 字符串,数字,布尔…
  • 字段、倒排索引的相关配置 (分不分词,分词器的选择等)
  • Mapping 会把 JSON 文档映射成 Lucene 所需要的扁平格式
  • 一个Mapping属于一个索引的 Type
  • 每个文档都属于一个Type
  • 一个 Type 有同一个 Mapping 定义
  • 7.0 开始,不需要在 Mapping 定义中指定 type 信息

字段的数据类型

  • 简单类型
  • 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