Elasticsearch multi_match查询高亮未覆盖最后一个搜索词问题
问题原因
这是bool_prefix查询机制和默认高亮规则的固有表现,不是bug:
multi_match的bool_prefix类型会对查询文本分词:除最后一个词外的所有词按完整词条匹配,最后一个词按前缀匹配,这部分前缀匹配命中的是search_as_you_type字段自动生成的title._index_prefix子字段,不是存完整分词的title主字段。- 高亮默认开启
require_field_match: true配置,仅标记当前指定高亮字段(即配置里的title主字段)上直接命中的完整词条。最后一个词是在子字段上的前缀匹配,主字段的高亮逻辑识别不到,自然不会加<em>标签。 - 手动在查询末尾加空格本质是钻了分词规则的空子:末尾空格会被识别为词边界,原本的最后一个词会被当做普通完整词条去匹配主字段,所以能正常高亮,但属于非规范的hack写法,后续升级版本、更换分词器都可能失效,不建议使用。
规范解决方案
优先选第一种,配置最简单,适配所有search_as_you_type+bool_prefix的搜索场景:
方案1:关闭高亮的字段匹配限制
在高亮配置里将require_field_match设为false,允许高亮逻辑识别本次查询所有涉及字段上的匹配命中,不需要修改查询文本,也不需要额外配置子字段:
GET objects/_search { "query": { "multi_match": { "query": "Goldenen Vlies", "type": "bool_prefix", "fields": [ "title", "title._2gram", "title._3gram", "title._index_prefix" ] } }, "highlight": { "require_field_match": false, "fields": { "title": {} } }, "_source": false }
执行后返回的高亮结果会同时标记Goldenen和Vlies两个词,完全符合预期。
方案2:为高亮配置所有查询关联的字段
如果出于业务权限、字段隔离的考虑不能关闭require_field_match,可以把查询用到的所有主字段、子字段都加入高亮配置列表,同时设置number_of_fragments: 0避免返回多段碎片结果:
GET objects/_search { "query": { "multi_match": { "query": "Goldenen Vlies", "type": "bool_prefix", "fields": [ "title", "title._2gram", "title._3gram", "title._index_prefix" ] } }, "highlight": { "fields": { "title": { "number_of_fragments": 0 }, "title._2gram": { "number_of_fragments": 0 }, "title._3gram": { "number_of_fragments": 0 }, "title._index_prefix": { "number_of_fragments": 0 } } }, "_source": false }
这个方案效果和方案1完全一致,但配置冗余度高,无特殊需求不优先选择。
内容的提问来源于stack exchange,提问作者tvanbeek
相关产品推荐
相关产品推荐

