【Elasticsearch】定义索引结构的核心 -- Mapping

文章目录

  • [ES -- Mapping](#ES -- Mapping)
      • [一、Mapping 核心层级](#一、Mapping 核心层级)
      • 二、基础字段属性(必选/高频)
        • [1. `type` - 字段数据类型(核心)](#1. type - 字段数据类型(核心))
        • [2. `index` - 是否创建倒排索引](#2. index - 是否创建倒排索引)
        • [3. `store` - 是否单独存储字段](#3. store - 是否单独存储字段)
      • [三、文本字段专属属性(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. `format` - 日期格式(仅 date 类型)](#1. format - 日期格式(仅 date 类型))
        • [2. `coerce` - 自动类型转换](#2. coerce - 自动类型转换)
      • 五、通用高级属性
        • [1. `null_value` - 空值替代](#1. null_value - 空值替代)
        • [2. `ignore_malformed` - 忽略非法值](#2. ignore_malformed - 忽略非法值)
        • [3. `doc_values` - 文档值(排序/聚合)](#3. doc_values - 文档值(排序/聚合))
        • [4. `fielddata` - 文本字段排序(临时内存)](#4. fielddata - 文本字段排序(临时内存))
      • 六、嵌套对象(nested)专属属性
      • [七、Mapping 配置示例(完整)](#七、Mapping 配置示例(完整))
      • 八、关键注意事项
  • dynamic

ES -- Mapping

Elasticsearch(ES)中的 Mapping 是定义索引结构的核心,相当于关系型数据库的表结构(Schema),它描述了文档中每个字段(Field)的数据类型、分词方式、索引策略等核心属性。理解 Mapping 的字段配置,是优化 ES 检索性能和数据存储的关键。

一、Mapping 核心层级

Mapping 主要分为两层:

  1. 索引级配置:控制整个索引的元数据(如分词器、日期格式);
  2. 字段级配置:针对单个字段的精细化定义(核心)。

本文重点讲解字段级核心配置项,并按功能分类说明。

二、基础字段属性(必选/高频)

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"}
        }
      }
    }
  }
}

八、关键注意事项

  1. Mapping 不可变:字段类型一旦创建,无法修改(可新增字段),需修改类型需重建索引;
  2. 优先用 keyword 而非 text:仅需精确匹配/聚合的字段(如ID、状态)用 keyword,避免 text 分词浪费资源;
  3. 中文分词必装 IK 插件:ES 默认分词器对中文不友好,生产环境需安装 IK 分词器;
  4. 避免过度开启 fielddata :text 字段排序/聚合优先用 fields.keyword,而非开启 fielddata;
  5. 合理设置 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),生产环境建议:

  1. 先关闭动态映射(dynamic: false/strict);
  2. 提前定义所有字段的 Mapping;
  3. 仅对日志等无固定结构的场景开启 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分词)
}

六、关键注意事项

  1. 动态映射的性能开销dynamic: true 会在写入时动态更新 Mapping,高频写入场景可能引发性能问题;
  2. Mapping 膨胀风险 :无限制的动态映射会导致索引的字段数量暴增(如日志中的随机字段名),引发「字段爆炸」,建议设置 index.mapping.total_fields.limit(默认1000)限制字段数量;
  3. 严格模式的容错性dynamic: strict 会直接拒绝包含未知字段的文档,需确保业务写入的字段全部提前定义;
  4. 动态模板的优先级:显式定义的 Mapping > 动态模板 > ES 默认动态映射。

总结:dynamic 字段是 ES 控制 Schema 灵活性的核心,生产环境需根据业务场景选择:

  • 固定结构数据(订单、用户):dynamic: strict + 手动定义 Mapping;
  • 半固定结构数据(商品):dynamic: false + 按需新增字段;
  • 无固定结构数据(日志):dynamic: true + 动态模板自定义规则。
相关推荐
蚁巡信息巡查系统8 小时前
政务网站巡查如何解决合规化问题?
大数据·运维·人工智能
中科天工8 小时前
从“无人”到“无忧”:AI与5G如何驱动智能制造跃升
大数据·人工智能·智能
Data_agent8 小时前
微店店铺所有商品API接口指南
java·大数据·服务器·windows·python
Mr数据杨9 小时前
我把经验写成工作流,将输出做成可复用的系统
大数据·网络·人工智能
五度易链-区域产业数字化管理平台9 小时前
技术实战 | 五度易链一站式大数据治理体系架构详解
大数据·ai
TTBIGDATA9 小时前
【Ambari开启Kerberos】Knox 接入 Trino web-ui 解决方案
大数据·运维·ambari·trino·knox·bigtop·ttbigdata
鲸采云SRM采购管理系统9 小时前
鲸采云SRM:灵活适配不同企业的采购业务模式
大数据
Elastic 中国社区官方博客9 小时前
Jina Reranker v3:用于 SOTA 多语言检索 的 0.6B 列表式重排序器
大数据·人工智能·elasticsearch·搜索引擎·ai·jina
深蓝易网9 小时前
打破数据滞后困局:让MES系统数据实时准确的实操方案
大数据·运维·人工智能·重构·制造
2501_941798739 小时前
面向微服务动态限流与服务熔断的互联网系统高可用设计与多语言工程实践分享
java·大数据·开发语言