Elasticsearch多匹配查询中如何获取最优匹配字段(不使用EXPLAIN)
不使用EXPLAIN获取multi_match各字段匹配相关性信息的方案
要在生产环境稳定获取每个字段的匹配相关性(包括最优匹配字段、各字段得分排序),可采用以下两种方案:
方案一:带命名查询的bool should + script_fields计算单字段得分
将原multi_match拆分为bool查询的should子句,每个子句对应单个字段的match查询并添加名称,同时通过script_fields计算每个字段的匹配得分:
GET /_search { "query": { "bool": { "should": [ { "match": { "subject": { "query": "brown fox", "_name": "match_subject" } } }, { "match": { "message": { "query": "brown fox", "_name": "match_message" } } } ], "tie_breaker": 0.3 } }, "script_fields": { "subject_score": { "script": { "source": "doc['subject'].size() > 0 ? _score(doc, 'subject', params.query) : 0", "params": { "query": "brown fox" } } }, "message_score": { "script": { "source": "doc['message'].size() > 0 ? _score(doc, 'message', params.query) : 0", "params": { "query": "brown fox" } } } } }
_name参数会在结果的matched_queries数组中返回匹配的字段查询名称,可快速判断哪些字段存在匹配;script_fields中的脚本通过_score函数计算单个字段的BM25得分,和原multi_match的得分逻辑完全一致;- 从
script_fields的结果中可直接对比各字段得分,确定最优匹配字段。
方案二:dis_max查询结合聚合(适用于批量统计场景)
如果需要批量统计字段匹配情况,可使用dis_max(best_fields本质基于dis_max)配合过滤聚合+top_hits,单文档场景优先选方案一:
GET /_search { "query": { "dis_max": { "queries": [ { "match": { "subject": "brown fox" } }, { "match": { "message": "brown fox" } } ], "tie_breaker": 0.3 } }, "aggs": { "subject_matches": { "filter": { "match": { "subject": "brown fox" } }, "aggs": { "top_subject_hits": { "top_hits": { "_source": ["subject"], "size": 1, "script_fields": { "subject_score": { "script": "_score(doc, 'subject', params.query)", "params": { "query": "brown fox" } } } } } } }, "message_matches": { "filter": { "match": { "message": "brown fox" } }, "aggs": { "top_message_hits": { "top_hits": { "_source": ["message"], "size": 1, "script_fields": { "message_score": { "script": "_score(doc, 'message', params.query)", "params": { "query": "brown fox" } } } } } } } } }
关键注意点
- 两种方案均避开了
explain的性能损耗,适合生产环境稳定运行; - 脚本中的
_score函数要求Elasticsearch 7.10及以上版本,低版本可手动用BM25公式编写脚本计算得分; - 若字段为分词字段,需保证脚本中的查询字符串和主查询使用相同分词器,确保得分计算一致。
内容的提问来源于stack exchange,提问作者Flying Kitty
相关产品推荐
相关产品推荐

