ElasticSearch 的Mapping 和常见字段类型

本文深入解析ElasticSearch中的Mapping概念,涵盖字段类型、Dynamic Mapping、字段索引控制、多字段类型等核心主题,帮助读者理解如何高效管理和优化ElasticSearch索引。

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

    truefalsestrict
    文档可索引
    字段可更新
    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
### Elasticsearch 中的 Mapping 字段类型Elasticsearch中,字段的数据类型定义了如何存储查询该字段的内容。每种数据类型的处理方式不同,因此选择合适的数据类型对于优化性能至关重要[^1]。 #### 基础数据类型 - **文本 (Text)**:适用于全文检索的字符串内容。通常会经过分词器处理以便于搜索操作。 - **关键字 (Keyword)**:用于精确匹配、聚合或者排序的字符串。不会被分割成多个词条而是作为一个整体对待。 - **数值型 (Numeric Types)**:包括`long`, `integer`, `short`, `byte`, `double`, `float`. 这些用来表示整数或浮点数,并支持范围查询等功能。 - **布尔值(Boolean)**:简单的真/假标志位。 - **日期(Date)**:时间戳或其他形式的时间表达式,能够解析多种格式并执行日期运算。 - **二进制(Binary)**:原始字节序列,常用于保存文件哈希等不可读取的信息。 #### 复杂数据结构 - **对象(Object Type)**:允许嵌套其他简单或复杂属性的对象。内部字段可以直接访问而无需扁平化整个文档。 - **数组(Array)**:任何基本类型都可以作为列表成员存在;即使是混合不同类型也是可行的,不过不建议这样做因为可能导致意外行为。 - **地理空间(Geo Point & Geo Shape)**:专门针对地理位置设计的支持坐标系转换以及距离计算的功能特性。 为了满足特定需求场景下的灵活性,还可以在同一物理字段上创建多重映射视图: ```json PUT my-index-000001 { "mappings": { "properties": { "city": { "type": "text", "fields": { "raw": { "type": "keyword" } } } } } } ``` 上述配置使得`city`既可用于自由文本查找又能在必要时充当分类标签参与统计分析[^2]。 值得注意的是,在较新的版本里,“_type”已被弃用,这意味着不再通过它来进行多态区分,转而在单个索引下统一管理所有记录实例[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值