Py学习  »  DATABASE

ES 支持哪些数据类型,和 MySQL 之间的映射关系是怎么样的?

小哈学Java • 2 天前 • 28 次点击  

在线 Java 面试刷题(已更新334题,图文并茂)https://www.quanxiaoha.com/java-interview

面试考察点

  1. 基础掌握度:数据类型是 Mapping 的地基。面试官想知道你是真的建过索引、写过 DSL,还是只在项目里 “摸过” ES。

  2. 选型能力text 和 keyword 选错、金额用了 double,这些在线上都是实打实的事故。类型选型直接暴露你的实践深度。

  3. 知识迁移能力:业务里最常见的场景就是 “MySQL 的数据同步到 ES 做搜索”。能不能把 MySQL 的概念、字段类型准确翻译成 ES 的,考察的是你对两套存储体系的理解,死记硬背应付不了追问。

核心答案

ES 的数据类型可以分成五大类:

分类
常用类型
一句话说明
核心类型
text
keyword
字符串二兄弟,一个分词一个不分
数字类型
long
integershortbytedoublefloathalf_floatscaled_float
整数 4 档,浮点 5 档
时间类型
date
既能存时间戳也能存格式化字符串
布尔类型
boolean
就是 true / false
复杂类型
object
nestedjoingeo_pointipdense_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 数据类型总览
ES 数据类型总览

深度解析

一、先搞懂 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**。生产上绝大多数字符串字段都是这个组合拳。

ES text 和 keyword 区别
ES 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 概念映射
MySQL 和 ES 概念映射

三、字段类型映射表(重点背这个)

MySQL 类型
ES 类型
注意事项
BIGINTlong
Java 的 Long 直接对应
INTinteger
32 位,Java 的 Integer
SMALLINT
 / TINYINT
short
 / byte
用得少,知道就行
DOUBLEdouble
64 位双精度
FLOATfloat
32 位单精度
DECIMAL scaled_float
⚠️ 重点,下面细说
VARCHAR
 / TEXT
text
 + keyword 子字段
搜索和精确匹配全都要
枚举、状态字段
keyword
不需要分词的直接上 keyword
DATETIME
 / TIMESTAMP
date
支持多种 format
TINYINT(1)
 / BOOLEAN
boolean
BLOBbinary
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

MySQL 字段映射 ES 类型
MySQL 字段映射 ES 类型

四、动态映射的坑

如果你建索引时没写 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,关掉不该开的自动检测,别把类型推断交给运气。

ES 动态映射误判
ES 动态映射误判

面试高频追问

  1. text 和 keyword 的区别? 必问。分词 vs 不分词、match vs term、倒排索引怎么建,三板斧答下来就稳了。

  2. 为什么 ES 7.0 要移除 Type? 不同 Type 共用同一份底层 Lucene 索引,字段会互相干扰(A Type 里字段是 date,B Type 里同名字段就得是 date),设计上就不合理,官方干脆砍了。

  3. nested 和 object 的区别?object 会把嵌套数组 “拍平”,丢失对象之间的边界,查 “颜色=红 且 尺寸=XL” 会误命中 “红L + 蓝XL”; nested 给每个嵌套对象单独建索引文档,保住边界,代价是查询稍慢、更新麻烦。

  4. MySQL 的数据怎么同步到 ES? 双写、Canal 监听 binlog、Flink CDC、Logstash 定时拉取,各有优劣,能对比着说就是加分项。

  5. 为什么 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 拍平),面试官对你的评价会直接上一个档次。

加入小哈的星球,你将获得: 专属的项目实战(4个项目) / 1v1 提问 / 简历修改 / Java 学习路线 / 社群讨论 / 学习打卡 / 每月赠书

  • 《仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍演示地址:http://116.62.199.48:7070/
  • Spring AI 应用(RAG 智能客服)》已完结, 基于 Spring AI + Spring Boot 3.x + JDK 21

  • 秒杀系统设计》正在更新中,单体到微服务高并发架构演进

  • 前后端分离博客项目(全栈开发) 已完结,演示链接:http://116.62.199.48/
  • 项目阅读地址:https://quanxiaoha.com/column

截止目前,累计输出 150w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 戳我加入学习,解锁全部项目,已有4900+小伙伴加入

图片
图片



    
图片

1. 我的私密学习小圈子,从0到1手撸企业实战项目~

2. Spring-Smart-DI 动态切换实现类,很不错!

3. 面试官:ElasticSearch 为什么快?

4. 每天骑的共享单车是什么通信原理,有人了解过吗?

图片


最近面试BAT,整理一份面试资料Java面试BATJ通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。

“在看”支持小哈呀,谢谢

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/200523