Elasticsearch:terms聚合输出大小写不匹配问题咨询
解决Elasticsearch Terms聚合返回小写值的问题
这问题我之前踩过坑!核心原因是你用到的gender和grade字段应该是被分词器处理过了——Elasticsearch默认的standard分词器会自动把大写字母转换成小写,所以哪怕你存储的时候是大写的AA,分词后索引里实际存的是小写的aa,terms聚合查的是分词后的索引数据,自然就返回小写结果啦。
给你几个实用的解决方案,按优先级排序:
方案1:直接将字段设为keyword类型(适合不需要全文搜索的字段)
如果gender、grade这类字段只需要做精确匹配和聚合,不需要按关键词模糊搜索,那直接在索引映射里把字段类型设为keyword就好——keyword类型不会做任何分词处理,存什么就索引什么,聚合时就能返回原始的大写值。
创建索引时的映射示例:
PUT /113 { "mappings": { "properties": { "gender": { "type": "keyword" }, "grade": { "type": "keyword" } } } }
如果索引已经存在,需要先删除重建(或者用reindex操作迁移数据),再设置这个映射。
方案2:给字段添加keyword子字段(兼顾全文搜索和聚合需求)
如果这些字段既要支持全文搜索(比如模糊匹配内容),又需要保留原始值做聚合,那最稳妥的方式是给字段添加一个keyword类型的子字段。
第一步:更新索引映射
如果索引已经存在,先关闭索引(部分ES版本支持动态更新可省略),然后执行映射更新:
PUT /113/_mapping { "properties": { "gender": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "grade": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }
第二步:重新索引数据
更新映射后,需要重新索引已有数据,让新的子字段生效:
POST _reindex { "source": { "index": "113" }, "dest": { "index": "113_new" } }
之后你可以删除原索引,把新索引重命名为113,或者直接在查询里使用新索引。
第三步:修改聚合查询,使用子字段
之后聚合时指定.keyword子字段即可:
POST /113/_search { "query": { "query_string": { "query": "Jack" } }, "aggs" : { "gender" : { "terms" : { "field" : "gender.keyword" } }, "grade" : { "terms" : { "field" : "grade.keyword", "order" : {"_count" : "asc"} } } } }
方案3:用脚本聚合临时转换(不推荐大数据量场景)
如果暂时没法修改映射和重索引,也可以用脚本把聚合结果转成大写,但这种方式会增加ES的计算压力,数据量大的时候性能会很差,仅作为临时应急方案:
POST /113/_search { "query": { "query_string": { "query": "Jack" } }, "aggs" : { "gender" : { "terms" : { "script" : { "source": "doc['gender'].value.toUpperCase()" } } }, "grade" : { "terms" : { "script" : { "source": "doc['grade'].value.toUpperCase()" }, "order" : {"_count" : "asc"} } } } }
总结一下:优先选方案2(兼顾搜索和聚合),如果字段不需要搜索就选方案1,方案3只适合临时救急哦。
内容的提问来源于stack exchange,提问作者Allen_Tsang
相关产品推荐
相关产品推荐

