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 设计时需要注意的点:
text
和keyword
的用途必须分清:分词和关键词(确定字段是否需要分词)- 确定字段是否需要独立存储
- 字段类型创建后不支持修改,谨慎创建
- 对不需要进行聚合/排序的字段禁用
doc_values
数据类型
基本数据类型
这里是大多数系统都支持的基本数据类型,他们有:
- binary:编码为 base64 字符串的二进制。
- boolean:仅支持
true
和false
的布尔类型。 - keyword:支持精准匹配的类型,另外还有
const_keyword
、wildcard
类型,支持聚合、排序功能 - text:全文检索类型
- 数字类型:integer、long、float、double 等
- 日期类型:date、date_nanos
keyword
与 text
对比:
-
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_hot
、data_warm
、data_cold
等
Mapping 内部数据
倒排索引
倒排存储是从单词到文档的映射关系的最佳实现形式。
倒排索引的特点:
- 在索引时创建
- 序列化到磁盘
- 全文搜索速度快
- 不适合做排序
- 默认开启
倒排索引适合的场景:
- 文本搜索引擎:作为搜索引擎的核心技术之一,倒排索引使搜索引擎能够迅速查询包含关键词的网页,为用户展示相关结果
- 文档检索系统:在知识库、图书馆等领域
- 企业内部搜索:搜索文件、邮件、会议记录
- 社交媒体分析:搜索话题和帖子
- 新闻和论文检索:搜索感兴趣关键词的新闻报告或者学术论文
- 数据挖掘:倒排索引适用于大量非结构化的数据,能结合数据挖掘算法来迅速找到包含有关键词的文本
正排索引
doc_values
被定义为“正排索引”。
在 Elasticsearch 中,正排索引(doc_values)是一种列式存储结构,默认情况下每个字段的 doc_values 都是激活的(除了 text 类型)。当字段索引时,Elasticsearch 为了能够快速检索,会把字段的值加入倒排索引,同时会存储该字段的正排索引。
正排索引的特点:
- 在索引时创建
- 序列化到磁盘
- 适合排序、聚合操作
- 将单个字段的所有值一起存储在单个数据列中
- 默认情况下,除
text
字段外所有字段类型均启用正排索引
fielddata
倒排索引用来解决那些文档包含这些关键词的问题,正排索引用来解决排序、聚合问题。当一个字段为 text
类型,它不支持正排索引,当 text
类型的字段被用于聚合、排序或者脚本操作时,fielddata
会在内存中按需构建相应的数据。
fielddata
是通过从磁盘读取每一字段的完整倒排索引,反正词项(term)与文档之间的关系,并将结果存储在 JVM 堆内存中构建。
fielddata 特点:
- 仅适用于
text
类型字段 - 在查询时在内存中创建,不会被持久化
- 默认情况下是被禁用,构建它很昂贵
_source
与 store
_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