Elasticsearch Mapping

目录

Elasticsearch Mapping 类似关系数据的的 schema(模式),Mapping 记录了索引的字段、字段数据类型,以及 Lucene 是怎样索引数据的。

在给新业务数据建索引时,需要进行的第一步就是 Mapping 设计,许多不重视的这个环节的,数据量增大后就暴露出了问题。

创建和修改 Mapping API

设计 Mapping 就是为索引字段指定数据和索引的方式。

可以在创建索引时指定 Mapping,Mapping 创建后不允许修改,可以继续添加 Mapping。

1、创建索引时指定 Mapping

PUT <INDEX_NAME>
{
  "settings": {},
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "analyzer": "standard"
      }
    }
  },
  "aliases": {}
}
# create index API

2、创建索引后添加 Mapping

PUT <INDEX>/_mapping
{
  "properties": {
    "email": {
      "type": "keyword"
    }
  }
}

在 Mapping 设计时需要注意的点:

  1. textkeyword 的用途必须分清:分词和关键词(确定字段是否需要分词)
  2. 确定字段是否需要独立存储
  3. 字段类型创建后不支持修改,谨慎创建
  4. 对不需要进行聚合/排序的字段禁用 doc_values

数据类型

基本数据类型

这里是大多数系统都支持的基本数据类型,他们有:

  • binary:编码为 base64 字符串的二进制。
  • boolean:仅支持 truefalse 的布尔类型。
  • keyword:支持精准匹配的类型,另外还有 const_keywordwildcard 类型,支持聚合、排序功能
  • text:全文检索类型
  • 数字类型:integer、long、float、double 等
  • 日期类型:date、date_nanos

keywordtext 对比:

  • keyword:不分词,使用正排索引,支持聚合,范围查询

  • text :分词,使用倒排索引,用于全文检索,不适用于聚合

复杂数据类型

复杂数据类型是常见数据类型的组合。

  • array 数据类型,所有元素的类型必须相同
  • object 数据类型,存储嵌套的 JSON
  • nested 数据类型,存储嵌套的 JSON
  • flattened 数据类型,存储嵌套的 JSON,Elasticsearch 7.3 新增的数据类型
  • Join 父子关系类型

object、nested、flattened 数据类型对比:

  • object 类型:这是 Elasticsearch 存储 JSON 字段的数据类型,它将 JSON 字段拍平并为每个字段创建 Mapping,这些字段可以独立进行查询和聚合。
    • 优点:每个字段都创建了 Mapping,查询快
    • 缺点:JSON 拍平后的会丢失对象关系^[1]^; 容易造成 Mapping 膨胀^[2]^
  • nested类型:这是 Elasticsearch 提供的一种特殊数据类型,用于处理嵌套的 JSON 对象。与 object 类型不同,nested 类型会保留对象的内部结构,这使得它可以准确地处理包含多个对象的数组。然后,nested 查询和聚合比 object 类型复杂,它只能使用 nested 查询和聚合。
    • 优点:解决了 object 丢失 JSON 对象关系的缺点。
    • 缺点:查询复杂了;nested 存储查询更复杂。
  • flattened 类型:用于处理任意深度的嵌套对象,它将整个 JSON 对象存储为一个字段,兼具 object 的特性可很好防止了 Mapping 膨胀问题。

专用数据类型

  • 坐标数据类型:用于保持地理位置信息,例如经纬度。
  • IP 类型:表示 IPv4、IPv6 地址。
  • completion 类型:用于实现高效的不全功能。

Mapping 元数据

  • 标识元字段
    • _index:表示文档所属索引。
    • _id:文档 ID。
  • 文档源元字段
    • _source:表示文档的原始 JSON 对象。
    • _size:表示 _source 字段的大小,单位为字节。
  • 索引元字段
    • _field_names:表示给定文档中包含费控值的所有字段
    • _ignored:表示由于设置 ignore_malformed 而在索引时被忽略的字段
  • 路由元字段
    • _routing:用于将给定文档路由到指定分片
  • 其他元字段
    • _meta:可以自定义的元信息,通常理解为给索引加的必要注释信息
    • _tier:指定文档所属索引的数据层级别,如在查询文档是可以指定 data_hotdata_warmdata_cold

Mapping 内部数据

倒排索引

倒排存储是从单词到文档的映射关系的最佳实现形式。

倒排索引的特点:

  • 在索引时创建
  • 序列化到磁盘
  • 全文搜索速度快
  • 不适合做排序
  • 默认开启

倒排索引适合的场景:

  • 文本搜索引擎:作为搜索引擎的核心技术之一,倒排索引使搜索引擎能够迅速查询包含关键词的网页,为用户展示相关结果
  • 文档检索系统:在知识库、图书馆等领域
  • 企业内部搜索:搜索文件、邮件、会议记录
  • 社交媒体分析:搜索话题和帖子
  • 新闻和论文检索:搜索感兴趣关键词的新闻报告或者学术论文
  • 数据挖掘:倒排索引适用于大量非结构化的数据,能结合数据挖掘算法来迅速找到包含有关键词的文本

正排索引

doc_values 被定义为“正排索引”。

在 Elasticsearch 中,正排索引(doc_values)是一种列式存储结构,默认情况下每个字段的 doc_values 都是激活的(除了 text 类型)。当字段索引时,Elasticsearch 为了能够快速检索,会把字段的值加入倒排索引,同时会存储该字段的正排索引。

正排索引的特点:

  • 在索引时创建
  • 序列化到磁盘
  • 适合排序、聚合操作
  • 将单个字段的所有值一起存储在单个数据列中
  • 默认情况下,除 text 字段外所有字段类型均启用正排索引

fielddata

倒排索引用来解决那些文档包含这些关键词的问题,正排索引用来解决排序、聚合问题。当一个字段为 text 类型,它不支持正排索引,当 text 类型的字段被用于聚合、排序或者脚本操作时,fielddata 会在内存中按需构建相应的数据。

fielddata 是通过从磁盘读取每一字段的完整倒排索引,反正词项(term)与文档之间的关系,并将结果存储在 JVM 堆内存中构建。

fielddata 特点:

  • 仅适用于 text 类型字段
  • 在查询时在内存中创建,不会被持久化
  • 默认情况下是被禁用,构建它很昂贵

_sourcestore

_source 字段包含索引时传递的原始 JSON,它没有构建索引(因此无法搜索),但 ES 已经存储该字段,以便在执行搜索时将它返回。

_source 字段确实会引起存储开销,可以将其禁用,但是需要做好权衡。禁用 _source 后 reindex API、高亮、update 和 update_by_query API 都将不能使用。

store 可以只让 ES 存储部分文档字段,但副作用和禁用 _source 一样。

null_value 处理空值

null 是一个特殊值,在传统关系数据库中聚合和排序对它无效。在 ES 中,值为 null 的字段被认为无效,ES 不会索引它,后面就无法搜索到。但是业务中 null 有含义经常需要搜索,ES 提供了 null_value 配置选项,可以设置一个默认值,当搜索 null 值时可以用默认值进行代替。


参考:

[1] https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html