Elasticsearch按带分析器字段排序及映射报错问题求助
Elasticsearch 带分析器字段排序及多字段复用问题
问题场景
索引中字段映射如下:
"computedCompanyName": { "type": "text", "fields": { "exact": { "type": "text", "analyzer": "exact" }, "phon": { "type": "text", "analyzer": "phonetic" } } }
该字段值由业务逻辑计算生成,原始数据不存入索引。需根据用户选择,按computedCompanyName.exact或computedCompanyName.phon子字段排序,示例排序代码:
private SearchQuery createDefaultSortingConditions(NativeSearchQueryBuilder nativeSearchQueryBuilder) { nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("computedCompanyName.exact").order(SortOrder.ASC)); return nativeSearchQueryBuilder.build(); }
执行时遇到两个问题:
- 直接排序text子字段时,出现Fielddata禁用报错
- 将子字段改为keyword类型后,出现分析器不支持的映射报错,错误信息如下:
Suppressed: org.elasticsearch.client.ResponseException: method [PUT], host [http://localhost:9200], URI [/rt_test/_mapping/rechtstraegerindexeddata?master_timeout=30s&include_type_name=true&timeout=30s], status line [HTTP/1.1 400 Bad Request] Warnings: [[types removal] Specifying types in put mapping requests is deprecated. To be compatible with 7.0, the mapping definition should not be nested under the type name, and the parameter include_type_name must be provided and set to false.] {"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"Mapping definition for [fields] has unsupported parameters: [search_analyzer : phonetic] [analyzer : phonetic]"}],"type":"mapper_parsing_exception","reason":"Mapping definition for [fields] has unsupported parameters: [search_analyzer : phonetic] [analyzer : phonetic]"},"status":400} at org.elasticsearch.client.RestClient$SyncResponseListener.get(RestClient.java:936)
核心问题:
- 能否按带分析器的字段排序?
- 能否用同一
computedCompanyName字段同时实现搜索与排序?
解决方案与说明
1. 能否按带分析器的字段排序?
可以,但需调整映射设计,不能直接用text字段排序:
- 原因:Elasticsearch的text字段默认禁用fielddata(启用会占用大量堆内存),且text字段经分析器拆分后无法提供有序排序所需的精确值。
- 推荐方案:给带分析器的text子字段新增keyword子字段,用keyword字段负责排序,text字段保留分析器用于搜索。修改后的映射如下:
"computedCompanyName": { "type": "text", "fields": { "exact": { "type": "text", "analyzer": "exact", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "phon": { "type": "text", "analyzer": "phonetic", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }
排序时使用对应的keyword子字段:
// 按exact场景排序 nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("computedCompanyName.exact.keyword").order(SortOrder.ASC)); // 按phon场景排序 nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("computedCompanyName.phon.keyword").order(SortOrder.ASC));
- 不推荐方案:临时启用text字段的fielddata(仅适合测试场景),映射修改如下:
"computedCompanyName.exact": { "type": "text", "analyzer": "exact", "fielddata": true }
2. 能否用同一computedCompanyName字段同时实现搜索与排序?
完全可以,通过多字段嵌套设计即可实现:
- 主字段
computedCompanyName设为text类型,可配置默认分析器用于通用全文搜索 - 子字段
exact、phon保留text类型+对应分析器,满足精确匹配、语音搜索等特定需求 - 每个text子字段新增keyword子字段,负责对应场景的排序
- 搜索时可使用
computedCompanyName、computedCompanyName.exact或computedCompanyName.phon,排序时使用对应的.keyword子字段,实现同一主字段下的搜索与排序需求。
关于keyword类型报错的说明
直接将text子字段改为keyword会报错,因为keyword类型不支持analyzer参数,两者无法共存。必须通过多字段嵌套的方式,让text字段负责带分析器的搜索,keyword字段负责排序,各司其职。
内容的提问来源于stack exchange,提问作者Frankio1
相关产品推荐
相关产品推荐

