👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路
文章大纲 第2章 数据建模与高效写入:ES字段类型选择最佳实践:keyword vs text与nested对象深度解析 1. 索引设计核心原则 2. `keyword`与`text`类型终极对决 2.1 核心差异对比 2.2 性能基准测试数据 2.3 经典使用场景 3. `nested`对象深度解析 3.1 问题背景:`对象数组的扁平化---理解体会到扁平化这个词` 3.2 `nested`类型解决方案 3.3 nested与普通对象对比 3.4 性能影响测试 4. 实战案例:电商平台商品模型设计 4.1 需求分析 4.2 最终映射设计 4.3 查询示例:查找红色库存>100的商品 5. 最佳实践总结 5.1 类型选择决策树 5.2 黄金法则 5.3 常见误区 附录:性能优化参数参考
第2章 数据建模与高效写入:ES字段类型选择最佳实践:keyword vs text与nested对象深度解析
1. 索引设计核心原则
在Elasticsearch
中,字段类型的选择直接影响以下关键指标:
影响维度 说明 典型场景示例
查询性能 类型选择错误可能导致查询延迟增加5-10倍 使用text
类型进行精确匹配 存储效率 合理的类型可减少20-50%的磁盘占用 数值类型误设为keyword 聚合准确性 错误类型会导致cardinality聚合误差率高达30% 高基数字段使用text类型进行聚合 功能支持 特定功能(如地理位置查询)必须使用专用类型
geo_point用于地理位置查询
cardinality
是 Elasticsearch
中的一种聚合类型,它可以对指定字段中的唯一值进行近似计数。 这里的 “近似” 是因为为了在处理大规模数据时提高性能和减少内存使用,cardinality
采用了 HyperLogLog++
算法(算法的核心思想基于伯努利试验和概率统计)来估算唯一值的数量,而不是精确统计。
2. keyword
与text
类型终极对决
2.1 核心差异对比
特性 keyword类型
text类型
分词处理 不进行分词 默认使用标准分词器 存储结构 原始值完整存储 分词后存储倒排索引 查询方式 精确匹配(term查询)
全文搜索(match查询)
排序支持 完全支持 需要开启fielddata
(消耗内存) 聚合性能 高效,适合terms
聚合 需要额外配置fielddata
,性能较差 典型应用场景
标签、状态码、分类ID 文章内容、产品描述、日志详情 存储开销 每个值独立存储 分词后存储,可能有重复token 模糊查询 支持wildcard(性能差)
支持多种分词器(如ngram)
2.2 性能基准测试数据
测试环境 :3节点集群(16核32GB,NVMe SSD),数据集:1000万条商品记录
测试场景 keyword类型耗时
text类型耗时
性能差异 精确匹配查询(term) 23ms 520ms 22.6倍 全文搜索(match) N/A 45ms - terms聚合(1000桶) 680ms 4200ms 6.2倍 存储空间占用 12.4GB 18.7GB 1.5倍
2.3 经典使用场景
{ "product_id" : { "type" : "keyword" } , "category" : { "type" : "keyword" , "ignore_above" : 256 } , "status" : { "type" : "keyword" }
}
适用text
的情况 : analyzer
(分析器):将文本拆分成一个个独立的词项(term
),并可对这些词项进行一系列处理,如转换大小写、去除停用词等。ik_max_word
分词器特点 ik_max_word
是 IK
分词器提供的一种分词模式。IK 分词器是一款专门为中文文本处理设计的开源分词器,在 Elasticsearch
中被广泛应用 。ik_max_word
模式具有以下特点: 最大切分粒度 :它会将文本进行最细粒度的拆分,尽可能地将文本拆分成更多的有意义的词 。例如,对于 “研究生命起源” 这句话,ik_max_word
会将其拆分为 “研究”“研究生”“生命”“起源” 等词项,这样可以提高搜索的召回率,让更多可能相关的文档被检索出来。智能识别 :能够智能识别中文词汇,包括一些常见的专业术语、人名、地名等 ,使得分词结果更符合中文语言习惯。
{ "product_description" : { "type" : "text" , "analyzer" : "ik_max_word" , "fields" : { "keyword" : { "type" : "keyword" } } }
}
3. nested
对象深度解析
3.1 问题背景:对象数组的扁平化---理解体会到扁平化这个词
{ "order_id" : "1001" , "items" : [ { "sku" : "A001" , "price" : 99 } , { "sku" : "B002" , "price" : 199 } ]
}
{ "order_id" : "1001" ,"items.sku" : [ "A001" , "B002" ] ,"items.price" : [ 99 , 199 ]
}
3.2 nested
类型解决方案
{ "order" : { "properties" : { "items" : { "type" : "nested" , "properties" : { "sku" : { "type" : "keyword" } , "price" : { "type" : "double" } } } } }
}
3.3 nested与普通对象对比
特性 nested类型 普通对象数组 存储方式 独立隐藏文档 扁平化存储 查询准确性 精确维护对象关系 可能产生跨对象匹配 写入性能
比普通对象慢2-3倍
最优 查询性能 需要特殊查询语法,较慢 标准查询语法 适用场景 需要精确维护对象关系的场景
不需要维护关系的简单数组 内存消耗 每个nested对象单独索引 整体作为字段处理
3.4 性能影响测试
测试数据集 :500万订单记录,每个订单平均3个商品项
操作类型 nested类型耗时 普通对象耗时 差异倍数
写入吞吐量 1,200 docs/s 3,800 docs/s 3.2倍 嵌套查询 220ms 35ms 6.3倍 聚合分析 1.8s 0.9s 2倍 存储空间 143GB 89GB 1.6倍
4. 实战案例:电商平台商品模型设计
4.1 需求分析
商品基础信息 多规格SKU
管理 用户评论情感分析 实时库存查询
4.2 最终映射设计
{ "mappings" : { "properties" : { "product_id" : { "type" : "keyword" } , "title" : { "type" : "text" , "analyzer" : "ik_smart" , "fields" : { "keyword" : { "type" : "keyword" } } } , "categories" : { "type" : "keyword" } , "specs" : { "type" : "nested" , "properties" : { "color" : { "type" : "keyword" } , "size" : { "type" : "keyword" } , "stock" : { "type" : "integer" } } } , "reviews" : { "type" : "nested" , "properties" : { "user_id" : { "type" : "keyword" } , "content" : { "type" : "text" } , "rating" : { "type" : "byte" } } } } }
}
ik_smart
是 IK
分词器提供的一种分词模式。IK
分词器是专为中文文本处理打造的开源分词器,在 Elasticsearch
社区被广泛应用。ik_smart
模式具有以下显著特点: 最少切分原则 :它会尽可能将文本进行最粗粒度的拆分,以最少的词数来表达文本的语义 。例如,对于 “研究生命起源” 这句话,ik_smart
会将其拆分为 “研究”“生命起源”,这种切分方式更注重整体语义的表达。高效简洁 :由于分词结果的词数相对较少,在处理大规模文本时,ik_smart 可以减少索引的大小,提高搜索效率
,同时也能一定程度上降低计算资源的消耗。使用场景 对搜索效率要求高的场景 :当需要快速处理大量中文文本搜索请求时,ik_smart
是一个不错的选择。例如,在电商网站的商品搜索功能中,用户输入搜索关键词后,系统需要迅速返回相关商品列表,使用 ik_smart
可以加快搜索速度,提升用户体验。注重整体语义匹配的场景 :在一些对文本整体语义理解要求较高的搜索场景中 ,ik_smart
的粗粒度分词能够更好地捕捉文本的核心语义 。比如,在企业知识管理系统中搜索相关文档时,用户更关注的是文档的整体主题,ik_smart
可以帮助找到更符合主题的文档。
4.3 查询示例:查找红色库存>100的商品
{ "query" : { "nested" : { "path" : "specs" , "query" : { "bool" : { "must" : [ { "term" : { "specs.color" : "red" } } , { "range" : { "specs.stock" : { "gt" : 100 } } } ] } } } }
}
5. 最佳实践总结
5.1 类型选择决策树
是
否
是
否
是且需维护关系
否
需要全文搜索?
使用text类型
需要精确匹配?
使用keyword
包含子对象?
使用nested
使用合适的基础类型
5.2 黄金法则
标识性原则 :唯一标识符必须使用keyword
长度控制 :超过256
字符的keyword
字段需设置ignore_above
混合使用 :重要文本字段应同时设置text和keyword
性能代价 :nested
类型要严格控制数组长度 版本兼容 :7.x以上版本优先使用keyword替代string类型
5.3 常见误区
错误场景 后果
解决方案
对text字段进行term查询 返回结果不准确 使用match查询或.keyword字段 过度使用nested类型 写入性能急剧下降 评估是否真正需要对象关系维护
大数组存储为keyword 导致mapping爆炸 使用flattened类型替代 数值字段设为text
范围查询效率降低80%
严格使用数值类型
附录:性能优化参数参考
"category" : { "type" : "keyword" , "eager_global_ordinals" : true
} ,
"specs" : { "type" : "nested" , "include_in_parent" : true
}