Elasticsearch邮编模糊搜索前缀匹配权重提升及查询选型
邮编模糊搜索排序优化方案
问题根因
你当前使用的ngram分词器会将邮编的所有长度为2~40的连续子串全部切分为索引term,不会记录子串在原始邮编中的位置信息,因此所有包含110子串的文档初始相关性分数差异很小,无法自动将以110开头的文档优先排序。
提升前缀匹配权重的方法
有两种常见实现思路:
- 查询侧加权:在查询逻辑中新增前缀匹配规则,给命中前缀的文档额外加权重,就是你给出的两种查询方案的核心逻辑
- 映射侧优化:给
zipcode字段新增一个keyword类型的子字段,专门用于前缀匹配、精确匹配场景,比查询text字段性能提升数倍,参考mappings修改如下:
"mappings": { "properties": { "zipcode": { "type": "text", "analyzer": "autocomplete", "search_analyzer": "autocomplete_search", "fields": { "keyword": { "type": "keyword" } } } } }
两种查询方案选型
方案1:prefix查询
GET test_index/_search { "query": { "prefix" : { "zipcode.keyword" : "110" } } }
- 适用场景:你只需要返回完全以110开头的邮编,不需要返回中间包含110的结果(比如示例中的
04110不需要返回) - 优势:写法简单,查询性能极高,keyword类型可以利用Elasticsearch的前缀索引优化,适合短字符串的前缀匹配场景
方案2:bool+should组合查询
GET test_index/_search { "query": { "bool": { "should": [ { "match": { "zipcode": "110" } }, { "match_phrase_prefix": { "zipcode.keyword": "110" } } ] } } }
- 适用场景:你需要返回所有包含110的邮编,同时要求以110开头的邮编排在最前面,兼顾模糊搜索需求和排序要求,符合你最初做邮编模糊搜索的设计初衷
- 优势:灵活性高,既保留了ngram的模糊匹配能力,又通过额外的前缀匹配条件给前缀命中的文档加了权重,排序完全符合预期
最终选型建议
如果你的业务需求就是用户输入任意片段都能搜到包含该片段的邮编,只是前缀匹配的优先级更高,选第二种组合查询方案。如果业务只需要前缀匹配的结果,选第一种prefix查询方案,成本更低性能更好。
内容的提问来源于stack exchange,提问作者amrit
相关产品推荐
相关产品推荐

