Elasticsearch添加通配符后查询失败问题排查与修复
问题原因与修复方案
我来帮你拆解下这个问题的核心原因和解决办法:
为什么加了尾缀通配符就查不到结果?
这本质是分词逻辑和通配符查询规则的冲突:
- 你的字段用的是ES默认的
text类型+标准分词器,当索引Hofstetten-Grünau时,标准分词器会把连字符-当作分隔符,将整个字符串拆成两个独立词条:hofstetten和grünau,索引里根本不存在完整的Hofstetten-Grünau词条。 - 当你用
Hofstetten-Grünau*做query_string查询时,ES会把这个字符串当作一个完整的前缀词条去匹配,但索引里没有对应的完整词条,自然返回空结果。 - 而
Hofstetten*能查到结果,是因为索引里存在hofstetten这个分词后的词条,前缀匹配刚好命中。
修复方案(兼顾你的通配符需求)
因为你需要支持用户自由使用各种通配符、布尔查询,不能替换成match查询,最稳妥的方式是给字段添加不分词的keyword子字段,同时保留原text字段的分词能力,这样既能支持分词后的全文搜索,又能支持精确的通配符/前缀匹配。
步骤1:修改字段映射(用Jest注解配置)
假设你的字段名为ort,调整注解如下:
@Field(type = FieldType.Text) @MultiField( mainField = @Field(type = FieldType.Text), otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword, ignoreAbove = 256) } ) private String ort;
注:ES 5.x版本中text字段默认不会自动生成keyword子字段(ES6+才默认添加),所以必须手动配置这个多字段。
步骤2:调整查询语句
当用户需要做带连字符的通配符查询时,指定查询ort.keyword字段即可:
{ "query": { "query_string": { "query": "ort.keyword:Hofstetten-Grünau*" } } }
而用户原来的其他查询方式(比如hofstetten grünau、+ort:hofstetten-grünau)依然可以用原text字段正常工作,因为分词后的词条依然存在。
可选优化:自动适配两种查询场景
如果你不想让用户手动指定字段,可以用copy_to把字段内容复制到一个独立的keyword字段,然后在query_string的default_field里同时包含原text字段和keyword字段。不过这种方式要注意查询的相关性得分,避免keyword字段的匹配影响排序结果。
内容的提问来源于stack exchange,提问作者user1782357
相关产品推荐
相关产品推荐

