ES 支持哪些数据类型,和 MySQL 之间的映射关系是怎么样的?
一则或许对你有用的小广告
欢迎加入小哈的星球,你将获得:专属的实战项目(4个项目都能学) / 1v1 提问 / 简历修改 / Java 学习路线 / 社群讨论 / 学习打卡 / 每月赠书
《Spring AI 项目实战(问答机器人、RAG 智能客服、联网搜索)》已完结,基于
Spring AI + Spring Boot 3.x + JDK 21...,查看介绍《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...,查看介绍;演示链接:http://116.62.199.48:7070/《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接:http://116.62.199.48/
新开坑项目:《从零手撸:秒杀系统高并发优化实战》 正在更新中...,查看介绍
截止目前,星球内专栏累计输出 150w+ 字,讲解图 5110+ 张,还在持续爆肝中.. 后续还会上新更多项目,已有 4700+ 小伙伴加入学习,欢迎点击围观
面试考察点
-
基础掌握度:数据类型是 Mapping 的地基。面试官想知道你是真的建过索引、写过 DSL,还是只在项目里 “摸过” ES。
-
选型能力:
text和keyword选错、金额用了double,这些在线上都是实打实的事故。类型选型直接暴露你的实践深度。 -
知识迁移能力:业务里最常见的场景就是 “MySQL 的数据同步到 ES 做搜索”。能不能把 MySQL 的概念、字段类型准确翻译成 ES 的,考察的是你对两套存储体系的理解,死记硬背应付不了追问。
核心答案
ES 的数据类型可以分成五大类:
| 分类 | 常用类型 | 一句话说明 |
|---|---|---|
| 核心类型 | text、keyword |
字符串二兄弟,一个分词一个不分 |
| 数字类型 | long、integer、short、byte、double、float、half_float、scaled_float |
整数 4 档,浮点 5 档 |
| 时间类型 | date |
既能存时间戳也能存格式化字符串 |
| 布尔类型 | boolean |
就是 true / false |
| 复杂类型 | object、nested、join、geo_point、ip、dense_vector 等 |
对象、嵌套、父子、地理、向量 |
和 MySQL 的概念映射一张表说清楚:
| MySQL | ES | 备注 |
|---|---|---|
| Database | Index | ES 7.0 之后没有 Type 的概念了 |
| Table | Type(已废弃)→ 现在直接对应 Index | 老面试题里的 “Type” 是历史产物 |
| Row | Document | 一行数据就是一个 JSON 文档 |
| Column | Field | 文档里的一个字段 |
| Schema | Mapping | 定义字段名和类型 |
| SQL | Query DSL | 查询语言 |
深度解析
一、先搞懂 ES 独有的 text 和 keyword
这是和 MySQL 差异最大的地方,也是面试的重头戏。
MySQL 的 VARCHAR 一个字段既 WHERE name = '手机' 精确匹配,又 LIKE '%手机%' 模糊查询,一个字段两副面孔。到了 ES 这里,拆成了两个类型:
PUT /product
{
"mappings": {
"properties": {
"productName": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
上面这段是生产环境最经典的写法,拆开看:
text:会分词。写入 “小米折叠屏手机” 会被拆成 “小米”、“折叠屏”、“手机” 这些词条(term),建立倒排索引。适合全文检索,也就是match查询keyword:不分词,整条字符串原样进索引。适合精确匹配(term查询)、排序、聚合。注意默认ignore_above是 256,超过 256 个字符的内容不会被索引,这是个经典坑fields子字段:主字段用text做搜索,子字段用keyword做排序聚合。查询时用productName.keyword就能走精确匹配。一次定义,两种玩法
一句话记住:要搜用 text,要查(精确匹配)、要排序、要聚合用 keyword。生产上绝大多数字符串字段都是这个组合拳。
二、概念映射:从 MySQL 平移到 ES
对照着看就很清晰了:
- Database → Index:一个库对一个索引,隔离逻辑相同。但注意 ES 7.0 移除了 Type(就是老教程里 “Table 对应 Type” 的那个 Type),原因是 ES 的 Type 共用同一份 Lucene 索引,不同 Type 的字段会互相干扰,属于历史设计缺陷,8.x 彻底删干净了
- Row → Document:MySQL 一行是一条记录,ES 一条是一个 JSON 文档,字段结构可以不一样(Schema Free)
- Column → Field:字段的概念一致,但 ES 的字段类型在索引创建后不能改(底层是 Lucene 段的不可变结构),要改只能重建索引(reindex),这和 MySQL
ALTER TABLE的成本完全不是一个量级
三、字段类型映射表(重点背这个)
| MySQL 类型 | ES 类型 | 注意事项 |
|---|---|---|
BIGINT |
long |
Java 的 Long 直接对应 |
INT |
integer |
32 位,Java 的 Integer |
SMALLINT / TINYINT |
short / byte |
用得少,知道就行 |
DOUBLE |
double |
64 位双精度 |
FLOAT |
float |
32 位单精度 |
DECIMAL |
scaled_float |
⚠️ 重点,下面细说 |
VARCHAR / TEXT |
text + keyword 子字段 |
搜索和精确匹配全都要 |
| 枚举、状态字段 | keyword |
不需要分词的直接上 keyword |
DATETIME / TIMESTAMP |
date |
支持多种 format |
TINYINT(1) / BOOLEAN |
boolean |
— |
BLOB |
binary |
Base64 编码存储,不能搜索 |
JSON(5.7+) |
object / nested |
一对多必须用 nested,object 会 “拍平” 数据导致查询错乱 |
POINT(空间类型) |
geo_point |
ES 的地理检索比 MySQL 空间索引强太多 |
| — | ip、dense_vector |
ES 特色,MySQL 没有直接对应 |
重点说说 DECIMAL → scaled_float 这个坑。ES 没有真正的十进制精确类型,double 存金额会有精度问题(0.1 + 0.2 ≠ 0.3 这个经典问题)。scaled_float 的原理是指定一个 scaling_factor(比如 100),底层实际存的是 long(价格 19.99 存成 1999),展示时再除回去,既省空间又精确。所以订单金额这种字段,要么 scaled_float,要么直接 long 存 “分”,别裸用 double。
四、动态映射的坑
如果你建索引时没写 Mapping,ES 会自动推断类型,这就是动态映射(Dynamic Mapping)。推断规则大致是:
- JSON 整数 →
long(不是integer) - JSON 浮点数 →
float(不是double) true/false→boolean- 字符串 →
text+keyword子字段 - 符合日期格式的字符串 →
date(默认开启日期检测,date_detection)
坑就在最后一条:假设有个字段存商品编号,前几条数据恰好长得很像日期(比如 “2024-01-15”),ES 会把它推断成 date,后面再来一条普通编号 “SP001”,直接写入失败。所以生产环境一律建议显式定义 Mapping,关掉不该开的自动检测,别把类型推断交给运气。
面试高频追问
-
text 和 keyword 的区别? 必问。分词 vs 不分词、
matchvsterm、倒排索引怎么建,三板斧答下来就稳了。 -
为什么 ES 7.0 要移除 Type? 不同 Type 共用同一份底层 Lucene 索引,字段会互相干扰(A Type 里字段是 date,B Type 里同名字段就得是 date),设计上就不合理,官方干脆砍了。
-
nested 和 object 的区别?
object会把嵌套数组 “拍平”,丢失对象之间的边界,查 “颜色=红 且 尺寸=XL” 会误命中 “红L + 蓝XL”;nested给每个嵌套对象单独建索引文档,保住边界,代价是查询稍慢、更新麻烦。 -
MySQL 的数据怎么同步到 ES? 双写、Canal 监听 binlog、Flink CDC、Logstash 定时拉取,各有优劣,能对比着说就是加分项。
-
为什么 ES 的字段类型定义后不能改? 底层 Lucene 段不可变,倒排索引结构建好就固定了。要改类型只能建新索引 +
_reindex迁移。
常见面试变体
- 变体一:“
text和keyword有什么区别,分别什么场景用?” - 变体二:“MySQL 的
LIKE '%xx%'和 ES 的全文检索有什么区别?”(考点:B+ 树无法利用前置 %,全表扫描 vs 倒排索引) - 变体三:“为什么有了 MySQL 还要 ES?两者怎么选型?”
记忆口诀
类型选择:搜用 text,查排聚合 keyword;整数 long,小数 scaled;日期 date,一对多 nested。
概念映射:库索引、行文档、列字段、表映射——Table 没了,Mapping 顶上。
总结
ES 数据类型按 “核心、数字、时间、布尔、复杂” 五大类记,重点是 text/keyword 的组合拳和 scaled_float 存金额。和 MySQL 的映射按 “Database→Index、Row→Document、Column→Field、Schema→Mapping” 对照理解,再记住 Type 已死这条版本演进线。能顺嘴说出两三个生产坑(keyword 256 上限、动态映射误判 date、object 拍平),面试官对你的评价会直接上一个档次。
