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

#中间件#面试八股

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

结论先行:ES 的字段类型分五族——字符串(text/keyword)、数值(long/integer/short/byte/double/float/half_float/scaled_float)、日期(date/date_nanos)、布尔与二进制、以及空间/对象/嵌套等特殊类型。与 MySQL 的映射不是一一对应:varchar 要按“是否分词”拆成 text 或 keyword,decimal 只能用 scaled_float 或字符串近似,json 对应 object/nested。

一、类型对照表

MySQLES 类型说明
varchar(全文检索)text分词,不能直接聚合排序
varchar(精确值/枚举)keyword不分词,可聚合、可排序
charkeyword定长精确匹配
tinyintbyte范围 -128~127
smallintshort范围 ±3.2 万
intinteger范围 ±21 亿
bigintlong64 位整数
floatfloat单精度,有精度损失
doubledouble双精度,仍非精确十进制
decimalscaled_float / keyword无原生 decimal,见后文
datetimedate支持毫秒,date_nanos 支持纳秒
tinyint(1) / bitbooleantrue/false
jsonobject / nested数组内对象需 nested 才能独立查询
blobbinary仅存储,不可检索
经纬度geo_point距离查询、地理聚合

二、text 与 keyword 的本质区别

维度textkeyword
是否分词是(standard/ik 等)否,整串入库
能否聚合不能(除非 fielddata)能
能否排序不能能
典型查询matchterm、terms
典型字段标题、正文状态、城市、ID、标签

一个字段同时要全文检索与聚合时,用 fields 多类型:

PUT /article
{
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "fields": {
          "raw": { "type": "keyword", "ignore_above": 256 }
        }
      }
    }
  }
}

title 走分词检索,title.raw 走精确聚合。

三、decimal 的三种替代

PUT /order
{
  "mappings": {
    "properties": {
      "amount_scaled": { "type": "scaled_float", "scaling_factor": 100 },
      "amount_str":    { "type": "keyword" },
      "amount_double": { "type": "double" }
    }
  }
}
方案精度可聚合适用
scaled_float定点,按因子缩放为 long是金额、单价(两位小数)
keyword 存字符串完全精确否(只能精确匹配)展示、对账
doubleIEEE754 浮点误差是统计近似值,不能用于账务

四、动态映射的坑

PUT /log/_doc/1
{ "traceId": "123456789012345678", "latency": 12 }

traceId 若被动态映射成 long,前导零与超长 ID 会失真;latency 若先写入字符串,后续数值查询会失败。生产上应关闭动态映射或使用模板:

PUT /_index_template/log_tpl
{
  "index_patterns": ["log-*"],
  "template": {
    "mappings": {
      "dynamic": "strict",
      "properties": {
        "traceId": { "type": "keyword" },
        "latency": { "type": "integer" }
      }
    }
  }
}

常见追问

  • 追问:nested 和 object 有什么区别?object 会把子字段打平,数组内对象的关联关系丢失;nested 为每个子对象建独立文档并维护关联,能用 nested 查询,但写入与查询成本更高。
  • 追问:为什么 text 不能聚合?聚合需要正排(doc → value),text 分词后没有稳定的“整串值”;开启 fielddata 可以强行聚合,但会把数据加载进堆,极易 OOM。
  • 追问:date 存时区吗?ES 内部统一存 UTC 毫秒时间戳,展示时按 format 与时区转换,写入时要带时区或 ISO8601 偏移量。

小结

  • 字符串按“是否分词”拆成 text 与 keyword,这是最常见的映射决策。
  • 数值类型按取值范围选,越窄越省空间。
  • decimal 用 scaled_float 或字符串,double 不能用于金额。
  • 生产索引建议 dynamic: strict 加模板,避免动态映射埋雷。
笔记加载中…