上一篇【第37篇】Elasticsearch集群路由与分片管理下一篇【第39篇】Elasticsearch SQL接口——用熟悉的SQL语法查询ES摘要映射Mapping是Elasticsearch中定义索引结构的核心机制类似于关系数据库中的Schema。正确的映射设计直接影响搜索精度、存储效率和查询性能。本文将全面讲解Elasticsearch的数据类型体系从基础类型text、keyword、数值、日期到复杂类型object、nested、地理坐标深入分析text与keyword的区别与选择策略详解scaled_float精确小数、date多格式支持等高级特性。此外还将涵盖index、store、doc_values、copy_to、fields等关键映射属性以及动态映射dynamic和动态模板dynamic_templates的配置方法帮助你在实际项目中设计出高效的索引映射方案。一、映射概述1.1 什么是映射映射Mapping定义了索引中文档的结构包括每个字段的数据类型、存储属性、分析器配置等。它类似于关系数据库中的表结构定义Schema但比关系数据库更加灵活。基本映射定义示例PUTmy_index{mappings:{properties:{title:{type:text},name:{type:text},age:{type:integer},created:{type:date,format:yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis}}}}1.2 为什么映射设计如此重要搜索精度正确的数据类型和分词器确保搜索结果准确存储效率合理的类型选择可以显著减少磁盘占用查询性能doc_values、index等属性的配置直接影响查询速度数据一致性映射定义了数据的校验规则二、核心数据类型全览2.1 数据类型总览表Elasticsearch提供了丰富的数据类型涵盖字符串、数值、日期、布尔、二进制、地理坐标等多种场景类型分类具体类型说明使用场景字符串text全文检索会分词文章标题、商品描述keyword精确匹配不分词状态码、标签、ID数值integer32位有符号整数年龄、数量long64位有符号整数时间戳、大数值short16位有符号整数端口号byte8位有符号整数标志位double64位双精度浮点科学计算、坐标float32位单精度浮点价格、评分half_float16位半精度浮点低精度数值scaled_float带缩放因子的浮点价格精确小数日期date日期时间创建时间、更新时间布尔boolean布尔值是否发布、是否激活二进制binaryBase64编码二进制图片哈希、加密数据IPipIPv4/IPv6地址客户端IP、服务器IP地理geo_point经纬度点位置搜索、距离计算geo_shape地理形状多边形区域、地理围栏复合objectJSON对象嵌套结构扁平化nested嵌套对象独立多值对象精确查询flattened扁平化键值对动态字段结构2.2 字符串类型text vs keyword这是Elasticsearch中最重要也是最容易被误解的类型选择。text类型text类型适用于全文检索场景字段值在索引前会经过分析器Analyzer处理被切分为多个Term词项PUTarticles{mappings:{properties:{title:{type:text,analyzer:ik_max_word,search_analyzer:ik_smart},content:{type:text}}}}对于title字段值为Elasticsearch权威指南索引后的Termelasticsearch、权威、权威指南、指南可以通过任意一个Term进行搜索keyword类型keyword类型适用于精确匹配场景字段值不做任何处理作为一个完整的Term存储PUTproducts{mappings:{properties:{status:{type:keyword},tags:{type:keyword},product_id:{type:keyword}}}}对于status字段值为published索引后的Termpublished完整值只能精确匹配published不会匹配publish或pubtext vs keyword 对比表对比维度textkeyword分词处理会分词不分词索引方式倒排索引按Term倒排索引按完整值搜索方式全文搜索match、multi_match精确匹配term、terms聚合支持不支持需用fielddata支持排序支持不支持支持适用场景文章内容、商品描述状态码、ID、标签分析器需要配置不需要多字段映射fields在实际项目中一个字段往往既需要全文搜索又需要精确匹配和聚合。此时可以使用fields属性为同一字段定义多种映射PUTproducts{mappings:{properties:{product_name:{type:text,analyzer:ik_max_word,fields:{keyword:{type:keyword,ignore_above:256},english:{type:text,analyzer:english}}}}}}使用方式// 全文搜索GETproducts/_search{query:{match:{product_name:苹果手机}}}// 精确匹配GETproducts/_search{query:{term:{product_name.keyword:Apple iPhone 15}}}// 聚合GETproducts/_search{aggs:{by_name:{terms:{field:product_name.keyword}}}}2.3 数值类型详解类型选择原则Elasticsearch支持多种数值类型选择的原则是在满足需求的前提下使用最小的类型以节省存储空间类型字节数取值范围byte1-128 ~ 127short2-32768 ~ 32767integer4-2^31 ~ 2^31-1long8-2^63 ~ 2^63-1float4单精度32位IEEE 754double8双精度64位IEEE 754half_float2半精度16位IEEE 754PUTmetrics{mappings:{properties:{response_code:{type:short},response_time:{type:float},bytes_sent:{type:long},score:{type:float}}}}scaled_float精确小数浮点数在计算机中存在精度问题如0.1 0.2 0.30000000000000004。scaled_float通过将浮点数乘以一个缩放因子scaling_factor存储为整数来解决精度问题PUTproducts{mappings:{properties:{price:{type:scaled_float,scaling_factor:100}}}}工作原理实际值: 99.99 scaling_factor: 100 存储值: 9999 (long类型)scaling_factor可支持的小数位数示例101位99.9 → 9991002位99.99 → 999910003位99.999 → 99999提示scaling_factor的最佳值取决于业务需求中需要保留的小数位数。例如商品价格通常保留2位小数使用scaling_factor: 100即可。2.4 日期类型基本用法Elasticsearch中的日期类型非常灵活支持多种输入格式PUTevents{mappings:{properties:{timestamp:{type:date}}}}支持以下格式的日期值POSTevents/_doc{timestamp:2026-05-22// 纯日期}POSTevents/_doc{timestamp:2026-05-22T10:30:00// ISO 8601}POSTevents/_doc{timestamp:2026/05/22 10:30:00// 自定义格式}POSTevents/_doc{timestamp:1747876200000// 毫秒时间戳}自定义日期格式PUTlogs{mappings:{properties:{log_time:{type:date,format:yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis},create_time:{type:date,format:strict_date_optional_time||epoch_millis}}}}使用||分隔符可以指定多种格式Elasticsearch会按顺序尝试每种格式直到匹配成功。第一个格式用于将内部时间戳转换回字符串显示。2.5 地理位置类型geo_pointgeo_point类型用于存储经纬度坐标支持多种输入格式PUTlocations{mappings:{properties:{location:{type:geo_point}}}}// 对象格式POSTlocations/_doc{location:{lat:39.9042,lon:116.4074}}// 字符串格式POSTlocations/_doc{location:39.9042,116.4074}// 数组格式经度在前POSTlocations/_doc{location:[116.4074,39.9042]}// Geohash格式POSTlocations/_doc{location:wx4gd0y0}地理边界框查询示例GETlocations/_search{query:{geo_bounding_box:{location:{top_left:{lat:40.0,lon:116.0},bottom_right:{lat:39.8,lon:116.5}}}}}geo_point vs geo_shape对比维度geo_pointgeo_shape存储内容单个经纬度点点、线、多边形等复杂形状查询方式距离查询、边界框包含、相交、不相交存储开销小较大适用场景门店位置、用户定位行政区域、地理围栏三、对象类型object vs nested3.1 object类型object类型用于存储JSON对象。在Elasticsearch中object类型会被扁平化处理即内部字段的路径会合并PUTblogs{mappings:{properties:{title:{type:text},author:{type:object,properties:{name:{type:keyword},email:{type:keyword}}}}}}索引文档POSTblogs/_doc{title:Elasticsearch入门,author:{name:张三,email:zhangsanexample.com}}扁平化后在Lucene中的实际存储结构author.name 张三 author.email zhangsanexample.comobject类型的局限由于扁平化处理object内部对象之间的关联关系会丢失。例如一个博客有多条评论如果用object类型存储对评论作者和内容的独立查询会出现交叉匹配问题。3.2 nested类型nested类型解决了object类型的关联丢失问题。每个nested对象被作为独立隐藏文档存储PUTblogs{mappings:{properties:{title:{type:text},comments:{type:nested,properties:{author:{type:keyword},content:{type:text},rating:{type:integer}}}}}}查询nested对象需要使用nested查询GETblogs/_search{query:{nested:{path:comments,query:{bool:{must:[{term:{comments.author:李四}},{range:{comments.rating:{gte:4}}}]}}}}}object vs nested 对比对比维度objectnested存储方式扁平化独立隐藏文档对象间关联丢失保持查询方式直接查询需使用nested查询性能更快较慢聚合可能交叉匹配精确聚合适用场景简单嵌套、无需独立查询多值对象、需独立查询四、重要映射属性详解4.1 index属性index属性控制字段是否被索引加入倒排索引。设置为false后该字段不能用于搜索但仍可以获取原始值PUTlogs{mappings:{properties:{user_agent:{type:keyword,index:false},user_id:{type:keyword,index:true}}}}注意index: false的字段不能用于搜索、排序和聚合但仍然可以从_source中获取原始值。适用于仅需存储但不需要搜索的字段如原始User-Agent字符串。4.2 store属性默认情况下字段值被索引但不单独存储。store: true会将字段的原始值单独存储在只需要获取特定字段时避免解析整个_sourcePUTarticles{mappings:{properties:{title:{type:text,store:true},date:{type:date,store:true},content:{type:text}}}}查询时使用stored_fields获取存储的字段GETarticles/_search{stored_fields:[title,date],query:{match:{content:Elasticsearch}}}最佳实践在大多数场景下不需要设置store: true。通过_source过滤_source_includes可以更灵活地获取字段。仅在文档非常大且频繁需要访问少量字段时才考虑使用store。4.3 doc_values属性doc_values是磁盘上的列式存储数据结构用于支持排序、聚合和脚本访问。几乎所有字段类型默认都启用doc_valuesPUTmetrics{mappings:{properties:{status_code:{type:keyword},session_id:{type:keyword,doc_values:false}}}}注意doc_values: false的字段仍可搜索但不能用于排序、聚合和脚本访问。text类型字段不支持doc_values需要用fielddata但fielddata消耗堆内存慎用。4.4 copy_to属性copy_to将多个字段的值复制到另一个字段实现多字段合并搜索PUTbooks{mappings:{properties:{title:{type:text,copy_to:all_fields},author:{type:text,copy_to:all_fields},description:{type:text,copy_to:all_fields},all_fields:{type:text}}}}搜索时只需查询all_fields字段GETbooks/_search{query:{match:{all_fields:Elasticsearch 权威指南}}}4.5 eager_global_ordinals全局序数Global Ordinals是用于优化keyword类型字段聚合性能的数据结构。eager_global_ordinals: true会在分片刷新时预构建全局序数PUTorders{mappings:{properties:{category:{type:keyword,eager_global_ordinals:true}}}}适用于字段基数唯一值数量较小且频繁聚合的场景。五、动态映射与动态模板5.1 dynamic属性dynamic属性控制Elasticsearch如何处理新字段的自动映射值行为true默认新字段自动检测类型并添加映射false新字段可以写入但不创建映射不可搜索strict新字段写入时报错拒绝文档PUTmy_index{mappings:{dynamic:strict,properties:{title:{type:text}}}}当尝试写入包含未定义字段的文档时strict模式会返回错误POSTmy_index/_doc{title:测试,new_field:value}{error:{root_cause:[{type:strict_dynamic_mapping_exception,reason:mapping set to strict, dynamic introduction of [new_field] within [_doc] is not allowed}]}}5.2 动态模板dynamic_templates动态模板允许根据字段名称或数据类型定义映射规则适用于字段名称有一定规律的日志数据PUTlogs{mappings:{dynamic_templates:[{strings_as_keywords:{match_mapping_type:string,mapping:{type:keyword,ignore_above:256}}},{long_fields:{match:*_count,mapping:{type:long}}},{date_fields:{match:*_time,mapping:{type:date,format:yyyy-MM-dd HH:mm:ss||epoch_millis}}},{ip_fields:{match:*_ip,mapping:{type:ip}}}]}}模板匹配规则参数说明示例match匹配字段名*countunmatch排除匹配text_*match_pattern正则匹配regexmatch_mapping_type匹配数据类型stringpath_match匹配完整路径metadata.*动态模板按定义顺序匹配第一个匹配的模板生效。六、映射属性综合对比属性默认值作用关闭的影响indextrue控制是否索引不可搜索、排序、聚合storefalse是否存储原始值不能用stored_fields获取doc_valuestrue非text列式存储不能排序、聚合dynamictrue动态映射控制影响新字段处理方式copy_to无字段值复制无不设置则不复制fields无多字段映射无ignore_above256超长值不索引超长值不可搜索七、总结与最佳实践核心要点字符串类型选择全文搜索用text精确匹配和聚合用keyword两者需要时用fields多字段映射数值类型最小化在满足需求前提下选择最小的数值类型使用scaled_float处理价格避免浮点精度问题nested解决关联查询多值对象需要独立查询时使用nested动态映射策略生产环境建议使用dynamic: strict或dynamic: false配合动态模板控制最佳实践清单索引创建前先规划好映射避免后期修改已有字段的类型不可更改为text字段配置合适的分析器中文场景使用IK分词器使用ignore_above: 256限制keyword字段的最大索引长度对不需要搜索的字段设置index: false节省空间对不需要排序和聚合的字段设置doc_values: false日志类索引使用动态模板统一处理未知字段使用索引模板Index Template管理批量索引的映射上一篇【第37篇】Elasticsearch集群路由与分片管理下一篇【第39篇】Elasticsearch SQL接口——用熟悉的SQL语法查询ES