文章目录
- [ES -- Mapping](#ES -- Mapping)
-
-
- [一、Mapping 核心层级](#一、Mapping 核心层级)
- 二、基础字段属性(必选/高频)
-
- [1. `type` - 字段数据类型(核心)](#1.
type- 字段数据类型(核心)) - [2. `index` - 是否创建倒排索引](#2.
index- 是否创建倒排索引) - [3. `store` - 是否单独存储字段](#3.
store- 是否单独存储字段)
- [1. `type` - 字段数据类型(核心)](#1.
- [三、文本字段专属属性(text 类型)](#三、文本字段专属属性(text 类型))
-
- [1. `analyzer` - 分词器](#1.
analyzer- 分词器) - [2. `search_analyzer` - 搜索时分词器](#2.
search_analyzer- 搜索时分词器) - [3. `fields` - 多字段映射](#3.
fields- 多字段映射) - [4. `ignore_above` - 忽略超长内容](#4.
ignore_above- 忽略超长内容) - [5. `boost` - 字段权重](#5.
boost- 字段权重)
- [1. `analyzer` - 分词器](#1.
- 四、数值/日期字段专属属性
-
- [1. `format` - 日期格式(仅 date 类型)](#1.
format- 日期格式(仅 date 类型)) - [2. `coerce` - 自动类型转换](#2.
coerce- 自动类型转换)
- [1. `format` - 日期格式(仅 date 类型)](#1.
- 五、通用高级属性
-
- [1. `null_value` - 空值替代](#1.
null_value- 空值替代) - [2. `ignore_malformed` - 忽略非法值](#2.
ignore_malformed- 忽略非法值) - [3. `doc_values` - 文档值(排序/聚合)](#3.
doc_values- 文档值(排序/聚合)) - [4. `fielddata` - 文本字段排序(临时内存)](#4.
fielddata- 文本字段排序(临时内存))
- [1. `null_value` - 空值替代](#1.
- 六、嵌套对象(nested)专属属性
- [七、Mapping 配置示例(完整)](#七、Mapping 配置示例(完整))
- 八、关键注意事项
-
- dynamic
-
-
- [一、dynamic 的核心作用](#一、dynamic 的核心作用)
- [二、dynamic 的三种取值](#二、dynamic 的三种取值)
- [三、dynamic 的生效层级](#三、dynamic 的生效层级)
-
- [1. 索引级配置(全局)](#1. 索引级配置(全局))
- [2. Object/Nested 字段级配置(局部)](#2. Object/Nested 字段级配置(局部))
- 四、动态映射的类型推断规则
- 五、dynamic_templates(动态模板)
- 六、关键注意事项
-
ES -- Mapping
Elasticsearch(ES)中的 Mapping 是定义索引结构的核心,相当于关系型数据库的表结构(Schema),它描述了文档中每个字段(Field)的数据类型、分词方式、索引策略等核心属性。理解 Mapping 的字段配置,是优化 ES 检索性能和数据存储的关键。
一、Mapping 核心层级
Mapping 主要分为两层:
- 索引级配置:控制整个索引的元数据(如分词器、日期格式);
- 字段级配置:针对单个字段的精细化定义(核心)。
本文重点讲解字段级核心配置项,并按功能分类说明。
二、基础字段属性(必选/高频)
1. type - 字段数据类型(核心)
定义字段存储的数据类型,ES 6.x 后取消了多类型,每个索引仅支持 _doc 类型,字段类型决定了 ES 如何存储、索引和检索该字段。
| 类型分类 | 常见类型 | 用途说明 |
|---|---|---|
| 核心简单类型 | text |
文本类型,支持分词,用于全文检索(如文章内容、商品描述) |
keyword |
关键字类型,不分词,支持精确匹配/聚合(如订单号、状态、标签) | |
integer/long |
整数(32位/64位),支持数值检索、排序、聚合 | |
float/double |
浮点数(32位/64位) | |
boolean |
布尔值(true/false) | |
date |
日期类型,支持格式化(如 yyyy-MM-dd HH:mm:ss),可排序/范围检索 |
|
| 复杂类型 | object |
嵌套对象(如 {"user": {"name": "张三", "age": 20}}) |
nested |
嵌套数组对象(解决 object 数组的扁平化问题,如 [{"tag": "a"}, {"tag": "b"}]) |
|
array |
数组类型(无需显式定义,直接存储数组,类型由第一个元素决定,如 ["a","b"]) |
|
| 特殊类型 | ip |
IP 地址类型(支持 IPv4/IPv6,如 192.168.1.1) |
geo_point |
地理坐标(如经纬度,支持距离检索、范围检索) | |
completion |
自动补全类型(如搜索框联想) | |
alias |
字段别名(映射到已有字段,简化检索) |
2. index - 是否创建倒排索引
-
取值:
true(默认)/false -
作用:控制字段是否可被检索(倒排索引)。
index: false:字段仅存储,不参与检索(如图片URL、冗余描述);index: true:字段可检索(text/keyword 默认为 true,date/numeric 同理)。
-
示例:
json"avatar_url": { "type": "keyword", "index": false // 仅存储,不检索 }
3. store - 是否单独存储字段
- 取值:
false(默认)/true - 作用:ES 默认会将整个文档存储在
_source字段中,store: true会将该字段单独存储,可通过stored_fields单独获取(减少_source解析开销)。 - 注意:通常无需开启,
_source足够灵活,仅在超大文档且仅需获取少数字段时使用。
三、文本字段专属属性(text 类型)
text 类型用于全文检索,以下属性仅对 text 生效:
1. analyzer - 分词器
-
作用:定义文本字段的分词规则(索引和搜索时默认使用)。
-
常用值:
standard:ES 默认分词器(英文按词拆分,中文单字拆分);ik_smart/ik_max_word:IK 中文分词器(需手动安装插件);whitespace:按空格分词;keyword:不分词(等价于 keyword 类型)。
-
示例:
json"content": { "type": "text", "analyzer": "ik_max_word" // 中文细粒度分词 }
2. search_analyzer - 搜索时分词器
-
作用:覆盖搜索时的分词器(索引时用
analyzer,搜索时用search_analyzer)。 -
场景:索引时细粒度分词(ik_max_word),搜索时粗粒度(ik_smart),提升召回率。
-
示例:
json"content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" }
3. fields - 多字段映射
-
作用:为同一个字段创建多种索引方式(如 text 用于全文检索,keyword 用于聚合/排序)。
-
示例:
json"title": { "type": "text", "analyzer": "ik_max_word", "fields": { "keyword": { // 子字段:title.keyword "type": "keyword", "ignore_above": 256 // 超过256字符的内容不索引 } } }检索时:
title:全文检索;title.keyword:精确匹配/聚合(如aggs: {group_by_title: {terms: {field: "title.keyword"}}})。
4. ignore_above - 忽略超长内容
- 作用:超过指定长度的字符串不索引(仅对 text/keyword 生效)。
- 单位:字符数(UTF-8 编码),默认
2147483647(无限制)。 - 示例:
"ignore_above": 256→ 超过256字符的内容不参与检索。
5. boost - 字段权重
-
作用:提升字段的检索权重(影响相关性得分)。
-
取值:数字(默认 1.0),值越大权重越高。
-
示例:
json"title": { "type": "text", "boost": 2.0 // 标题权重是内容的2倍 }, "content": { "type": "text", "boost": 1.0 }
四、数值/日期字段专属属性
1. format - 日期格式(仅 date 类型)
-
作用:定义日期字段的解析格式,支持多格式(用
||分隔)。 -
常用值:
yyyy-MM-dd HH:mm:ss:常规日期格式;epoch_millis:毫秒时间戳;epoch_second:秒时间戳;strict_date_optional_time:ES 默认日期格式。
-
示例:
json"create_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||epoch_millis||yyyy-MM-dd" }
2. coerce - 自动类型转换
-
取值:
true(默认)/false -
作用:自动转换非法数值/日期为合法值(如字符串 "123" → 整数 123,"2023-13-01" → 报错)。
-
示例:
json"age": { "type": "integer", "coerce": false // 禁止自动转换,传入非整数直接报错 }
五、通用高级属性
1. null_value - 空值替代
-
作用:为
null/空值字段设置默认值(仅 keyword/数值/日期等类型支持,text 不支持)。 -
场景:避免空值无法参与聚合/检索。
-
示例:
json"status": { "type": "keyword", "null_value": "unknown" // null → "unknown" }
2. ignore_malformed - 忽略非法值
-
取值:
false(默认)/true -
作用:忽略字段类型不匹配的错误(如给 integer 字段传字符串,默认报错,开启后跳过该字段)。
-
示例:
json"age": { "type": "integer", "ignore_malformed": true // 传入"abc"则忽略该字段,不报错 }
3. doc_values - 文档值(排序/聚合)
-
取值:
true(默认)/false -
作用:ES 为支持排序/聚合的字段(keyword/数值/日期等)创建列式存储(doc_values),关闭后无法排序/聚合,但节省内存。
-
示例:
json"log_id": { "type": "keyword", "doc_values": false // 仅检索,不排序/聚合 }
4. fielddata - 文本字段排序(临时内存)
-
取值:
false(默认)/true -
作用:text 类型默认关闭 doc_values,若需对 text 排序/聚合,需开启 fielddata(基于内存构建倒排索引,性能差,建议用
fields定义 keyword 子字段)。 -
示例:
json"content": { "type": "text", "fielddata": true // 不推荐,优先用 content.keyword }
六、嵌套对象(nested)专属属性
nested 类型用于数组对象的独立索引(解决 object 类型扁平化导致的检索错误),核心属性:
json
"comments": {
"type": "nested", // 嵌套对象
"properties": {
"author": {"type": "keyword"},
"content": {"type": "text", "analyzer": "ik_smart"}
},
"include_in_parent": false, // 是否将嵌套字段暴露到父文档(默认false)
"include_in_root": false // 是否将嵌套字段暴露到根文档(默认false)
}
七、Mapping 配置示例(完整)
json
PUT /product
{
"mappings": {
"properties": {
"id": {"type": "long"},
"name": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {"type": "keyword", "ignore_above": 256}
}
},
"price": {"type": "double", "coerce": false},
"category": {"type": "keyword", "null_value": "other"},
"create_time": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss||epoch_millis"},
"tags": {"type": "keyword"}, // 数组,无需显式定义array
"seller": { // object 类型
"properties": {
"name": {"type": "keyword"},
"score": {"type": "float", "index": false}
}
},
"comments": { // nested 类型
"type": "nested",
"properties": {
"user": {"type": "keyword"},
"content": {"type": "text", "analyzer": "ik_smart"}
}
}
}
}
}
八、关键注意事项
- Mapping 不可变:字段类型一旦创建,无法修改(可新增字段),需修改类型需重建索引;
- 优先用 keyword 而非 text:仅需精确匹配/聚合的字段(如ID、状态)用 keyword,避免 text 分词浪费资源;
- 中文分词必装 IK 插件:ES 默认分词器对中文不友好,生产环境需安装 IK 分词器;
- 避免过度开启 fielddata :text 字段排序/聚合优先用
fields.keyword,而非开启 fielddata; - 合理设置 ignore_above:限制超长字段的索引,减少存储开销。
通过合理配置 Mapping 的各个字段属性,可大幅提升 ES 的检索性能、存储效率和数据准确性。
dynamic
在 Elasticsearch 中,dynamic(动态字段) 是 Mapping 中控制「未知字段(文档中未提前定义的字段)」是否自动创建映射的核心配置,也是 ES 灵活性的关键特性(区别于关系型数据库的严格 Schema)。
一、dynamic 的核心作用
当文档写入 ES 时,如果包含Mapping 中未定义的新字段 ,dynamic 配置决定了 ES 如何处理这些字段:
- 自动创建映射(动态映射);
- 忽略该字段(仅存储,不创建映射);
- 直接报错(拒绝写入文档)。
二、dynamic 的三种取值
| 取值 | 行为说明 | 适用场景 |
|---|---|---|
true |
(默认)自动检测新字段类型,创建映射并索引该字段(支持检索/聚合) | 快速迭代的业务(如日志、埋点) |
false |
不创建映射,字段仅存储在 _source 中(不可检索/聚合),不报错 |
需保留原始数据,但无需检索新字段 |
strict |
严格模式:遇到未定义的新字段直接报错,拒绝写入文档 | 强 Schema 约束的业务(如订单、用户) |
三、dynamic 的生效层级
dynamic 可在索引级 、object/nested 字段级 分别配置(精细化控制):
1. 索引级配置(全局)
控制整个索引的所有未知字段:
json
PUT /my_index
{
"mappings": {
"dynamic": "strict", // 全局严格模式
"properties": {
"name": {"type": "keyword"},
"age": {"type": "integer"}
}
}
}
此时写入包含未知字段 email 的文档会直接报错:
json
// 报错:[strict_dynamic_mapping_exception] mapping set to strict, dynamic introduction of [email] is forbidden
PUT /my_index/_doc/1
{
"name": "张三",
"age": 20,
"email": "zhangsan@test.com" // 未定义的新字段
}
2. Object/Nested 字段级配置(局部)
仅控制某个嵌套对象内的未知字段,不影响全局:
json
PUT /my_index
{
"mappings": {
"dynamic": "true", // 全局允许动态映射
"properties": {
"user": {
"type": "object",
"dynamic": "strict", // user 子对象严格模式
"properties": {
"name": {"type": "keyword"},
"age": {"type": "integer"}
}
},
"logs": {
"type": "object",
"dynamic": "false" // logs 子对象忽略未知字段
}
}
}
}
测试写入:
json
PUT /my_index/_doc/1
{
"user": {
"name": "张三",
"age": 20,
"email": "zhangsan@test.com" // user 内的未知字段 → 报错
},
"logs": {
"ip": "192.168.1.1",
"time": "2026-01-04" // logs 内的未知字段 → 仅存储,不创建映射
},
"phone": "13800138000" // 全局未知字段 → 自动创建 keyword 映射
}
四、动态映射的类型推断规则
当 dynamic: true 时,ES 会根据字段值自动推断类型,核心规则:
| 字段值示例 | 推断类型 | 说明 |
|---|---|---|
"hello" |
text + keyword |
同时创建 text(分词)和 keyword(精确匹配)子字段 |
123 |
long |
整数默认映射为 long |
123.45 |
double |
浮点数默认映射为 double |
true/false |
boolean |
布尔值 |
"2026-01-04" |
date |
日期字符串自动识别 |
["a", "b"] |
text + keyword |
数组类型由第一个元素决定 |
{"k": "v"} |
object |
嵌套对象 |
⚠️ 注意:动态映射的类型推断可能不符合预期(如整数 123 映射为 long 而非 integer),生产环境建议:
- 先关闭动态映射(
dynamic: false/strict); - 提前定义所有字段的 Mapping;
- 仅对日志等无固定结构的场景开启
dynamic: true。
五、dynamic_templates(动态模板)
如果需要「自定义动态映射规则」(而非 ES 默认推断),可使用 dynamic_templates,实现:
- 所有以
_id结尾的字段映射为 keyword; - 所有以
_num结尾的字段映射为 integer; - 所有字符串字段默认映射为 keyword(而非 text+keyword)。
示例:自定义动态模板
json
PUT /my_index
{
"mappings": {
"dynamic_templates": [
{
"strings_as_keyword": { // 模板1:所有字符串默认映射为 keyword
"match_mapping_type": "string",
"mapping": {
"type": "keyword"
}
}
},
{
"id_fields": { // 模板2:以 _id 结尾的字段映射为 keyword
"match": "*_id",
"mapping": {
"type": "keyword",
"ignore_above": 256
}
}
},
{
"num_fields": { // 模板3:以 _num 结尾的字段映射为 integer
"match": "*_num",
"mapping": {
"type": "integer",
"coerce": false
}
}
}
],
"properties": {
"name": {"type": "text", "analyzer": "ik_max_word"} // 显式定义的字段优先
}
}
}
写入测试文档:
json
PUT /my_index/_doc/1
{
"user_id": "1001", // 匹配模板2 → keyword
"age_num": 20, // 匹配模板3 → integer
"address": "北京市", // 匹配模板1 → keyword(而非默认的 text+keyword)
"name": "张三" // 显式定义 → text(IK分词)
}
六、关键注意事项
- 动态映射的性能开销 :
dynamic: true会在写入时动态更新 Mapping,高频写入场景可能引发性能问题; - Mapping 膨胀风险 :无限制的动态映射会导致索引的字段数量暴增(如日志中的随机字段名),引发「字段爆炸」,建议设置
index.mapping.total_fields.limit(默认1000)限制字段数量; - 严格模式的容错性 :
dynamic: strict会直接拒绝包含未知字段的文档,需确保业务写入的字段全部提前定义; - 动态模板的优先级:显式定义的 Mapping > 动态模板 > ES 默认动态映射。
总结:dynamic 字段是 ES 控制 Schema 灵活性的核心,生产环境需根据业务场景选择:
- 固定结构数据(订单、用户):
dynamic: strict+ 手动定义 Mapping; - 半固定结构数据(商品):
dynamic: false+ 按需新增字段; - 无固定结构数据(日志):
dynamic: true+ 动态模板自定义规则。