真实对一条混合字段的文档做Dynamic Mapping推断,验证ES如何区分JSON原生类型和看起来像数字的字符串,以及numeric_detection这个全局开关的真实作用范围。
代码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
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": "02139" ← JSON里带引号,是个字符串 Mapping真实结果: zipcode → type: text + keyword子字段 ← 不是long,也不是integer
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指定每个字段的类型,而不是依赖动态推断。
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
_mapping API 与 numeric_detection 索引设置