bigywater.tech
Elasticsearch · 8

Dynamic Mapping 如何自动推断字段类型

真实对一条混合字段的文档做Dynamic Mapping推断,验证ES如何区分JSON原生类型和看起来像数字的字符串,以及numeric_detection这个全局开关的真实作用范围。

基础类型推断
真实依据JSON值类型,不是内容猜测
数组字段
真实没有array类型,取元素类型
带引号的数字
真实默认仍是text,开numeric_detection才变数字

做的事:真实写入一条混合类型字段的文档,看ES怎么推断每个字段的类型

代码POST /dyn_test/_doc/1 { "name": "alice", "age": 30, "price": 19.99, "created_at": "2026-10-01", "zipcode": "02139", "active": true, "tags": ["a","b"] } GET /dyn_test/_mapping

验证:数字、日期、布尔真实被精确推断,字符串数组真实没有专门的array类型

实测 · 本机 Elasticsearch 8.15.0 执行输出
age        → type: long       ← 真实JSON数字30
price      → type: float      ← 真实JSON数字19.99
created_at → type: date       ← 真实字符串"2026-10-01"被自动识别成日期格式
active     → type: boolean    ← 真实JSON布尔值
name       → type: text + keyword子字段   ← 真实普通字符串的标准动态映射
tags       → type: text + keyword子字段   ← 真实数组没有单独的"array"类型,取元素类型

真实验证到的第一件事是ES压根没有"array"这个独立的字段类型——tags这个数组字段,Mapping里真实显示的类型跟它内部元素的类型完全一样(text),ES对待数组的方式是"一个字段可以出现多个值",而不是"这个字段的类型是数组",这也是为什么后续写入同名字段时,一个标量值和一个数组值真实可以混用,只要元素类型兼容。created_at这个日期字符串真实被自动识别成date类型,依赖的是ES默认的日期格式探测规则(yyyy-MM-dd这类常见格式),不是真的理解了这是日期,只是字符串格式匹配上了内置规则。

验证:zipcode看起来是数字,但真实只映射成了text,不是数字类型

实测 · 本机执行输出
"zipcode": "02139"   ← JSON里带引号,是个字符串
Mapping真实结果: zipcode → type: text + keyword子字段    ← 不是long,也不是integer
这是本文认为Dynamic Mapping最容易被误解的一点:ES的动态类型推断真实依据的是JSON值本身携带的类型信息(JSON规范里,"02139"带引号就是字符串,02139不带引号才是数字,而且这个具体数字在JSON里因为前导0其实是非法的),不是"看字符串内容像不像数字"去猜。zipcode真实被完整地当成字符串处理,映射成了跟name一样的text+keyword组合——这是真实合理的默认行为,因为邮编这类"看起来是数字但真实不该参与数值计算"的字段(前导0、不需要范围查询)本来就该是字符串/keyword类型;但这个默认行为也意味着,如果前端不小心把一个真正该是数值的字段用引号包成了字符串发过来,ES不会自动纠正,它会真实原样接受并建出一个text字段,后续想对它做数值范围查询会真实失败。

验证:打开numeric_detection之后,同样的带引号数字字符串真实变成了long

实测 · 本机执行输出
PUT /dyn_test3 {"mappings": {"numeric_detection": true}}
POST /dyn_test3/_doc/1 {"count": "30"}

Mapping真实结果: count → type: long    ← 同样带引号的"30",这次真实被识别成了数字

真实对比证明了numeric_detection这个索引级设置就是专门用来打开"猜测带引号的数字字符串也是数字"这条规则的开关——默认false时,zipcode那种值真实只会是文本;显式设成true之后,同样写法的"30"真实被映射成了long。这个开关真实是个全局性的索引设置,一旦打开会对这个索引里所有"看起来像数字的带引号字符串"字段都生效,不能针对单个字段开关——如果真实的数据源里既有需要被识别成数字的字段,又有像邮编这种故意要保留字符串形态的字段,numeric_detection这把全局开关就不够用了,真实需要提前用显式Mapping指定每个字段的类型,而不是依赖动态推断。

分步演示:从基础类型推断到numeric_detection开关

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

Dynamic Mapping真实依据JSON类型而非字符串内容推断
这一步新验证的字段

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动,非Docker)
    • 真实的 _mapping API 与 numeric_detection 索引设置
    京ICP备2026067502号-1京公网安备11010502063487号