bigywater.tech
Elasticsearch · 9

显式 Mapping 与 Dynamic Mapping 的差异

真实对比显式Mapping和上一篇验证过的Dynamic Mapping,看字段类型的精确程度和写入时的类型校验强度有什么真实差异。

显式keyword
真实不会额外生成text主字段
显式integer
真实比动态推断的long更省存储
写入校验
真实类型不匹配直接400拒绝整条写入

做的事:真实建一个带显式Mapping的索引,对比字段类型和写入校验的严格程度

代码PUT /exp_map { "mappings": { "properties": { "zipcode": {"type": "keyword"}, "age": {"type": "integer"} } } } POST /exp_map/_doc/1 {"zipcode": "02139", "age": 30} POST /exp_map/_doc/2 {"zipcode": "02140", "age": "not-a-number"}

验证:显式声明的zipcode真实直接就是keyword,不会像动态推断那样多生成一份text

实测 · 本机 Elasticsearch 8.15.0 执行输出
GET /exp_map/_mapping
→ zipcode → type: keyword     ← 真实只有keyword这一种类型,没有text主字段
→ age     → type: integer     ← 真实是比long更省空间的类型

对比本系列上一篇验证过的Dynamic Mapping默认行为(字符串字段真实会自动生成text主字段加keyword子字段两份),这次zipcode真实只有keyword一种类型——因为显式Mapping里只声明了keyword,ES不会自己"贴心"地再加一份text字段。age同理,动态推断给普通整数的默认类型真实是占8字节的long,这次显式声明成integer(4字节)真实生效了——这是显式Mapping真实的第一个价值:能精确控制每个字段该占多少存储、该不该同时支持全文检索和精确匹配,不需要接受动态推断给出的"过度安全"的默认选择。

验证:往显式integer字段写一个非数字字符串,真实整条写入被直接拒绝

实测 · 本机执行输出
POST /exp_map/_doc/2 {"zipcode": "02140", "age": "not-a-number"}
→ 400 document_parsing_exception:
  "failed to parse field [age] of type [integer] in document with id '2'.
   Preview of field's value: 'not-a-number'"
  caused_by: number_format_exception: For input string: "not-a-number"
这是显式Mapping真实最核心的意义:它不只是"预先声明类型"这么简单,而是真实在每一次写入时都会拿这份声明去校验传进来的值——age字段显式声明成integer之后,任何写入时真实无法解析成整数的值(本文这次是字符串"not-a-number"),ES会直接返回400拒绝整条写入,不会像Dynamic Mapping那样"来者不拒、以第一条文档的类型为准"。这跟上一篇验证的"动态推断只在字段第一次出现时决定类型,之后同名字段只要跟第一次的类型兼容就能写入"是完全不同的两种保护强度:动态Mapping的类型约束是"事后被动形成"的,显式Mapping的类型约束是"提前主动声明并在每次写入时强制校验"的。真实的工程含义是:对结构已知、字段类型不该随意变化的核心业务数据(订单号、金额、状态枚举),显式Mapping能在写入阶段就真实拦住脏数据,而不是等到查询阶段才发现某个字段里混进了意料之外的类型。

分步演示:从精确类型到写入时的强制校验

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

显式Mapping真实提供的精确类型和强制校验
这一步新验证的行为

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的显式 Mapping 声明与 document_parsing_exception
    京ICP备2026067502号-1京公网安备11010502063487号