《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.17.Text analysis, settings 及 mappings——3.4.2.17.3.全文搜索/精确搜索(13) https://developer.aliyun.com/article/1229926
4.5 multi_match
multi_match 查询,即多字段查询,区别于 term 和 match 对单一字段的查询,multi_match 扩展了搜索的范围。使用方式如下:
GET /_search { "query": { "multi_match" : { "query": "this is a test", "fields": [ "subject", "message" ] } } }
在 fields 内容中,使用者可以指定多个字段查询。
其中:
1、可以使用 * 代替字符进行 wildcard 匹配。比如:"fields": [ "title", "*_name" ] 代表
fisrt_name 和 last_name。注意,在使用 wildcard 匹配时,匹配到的字段数如果过多,则最大能查询的条件数受 indices.query.bool.max_clause_count 的限制,默认是1024。
2、可以使用 ^ 符号进行字段查询时的加权。比如:"fields" : [ "subject^3", "message" ],其中 subject 字段在算分时时 message 字段的三倍。
在多字段查询时,字段和被查询词项的关系主要有:best_fields/most_fields/cross_fields/phrase/phrase_prefix/bool_prefix,这六种关联方式。
best_fields
默认的查询方式,返回的文档排序按照其中某个字段得分最高的排在前面,这是一种单字段匹配优先的查询方式。
比如:查询 "brown fox",单个字段中出现 "brown fox" 的文档要比两个字段分别出现 brown 和 fox 的文档得分高。
best_fields 的方式是产生一个多 match 查询,然后将多个字段查询条件进行 dis_max 查询,将单字段得分高的排在前面。
类似于这样的查询:
GET /_search { "query": { "multi_match" : { "query": "brown fox", "type": "best_fields", "fields": [ "subject", "message" ], "tie_breaker": 0.3 } } }
执行起来是这样的:
GET /_search { "query": { "dis_max": { "queries": [ { "match": { "subject": "brown fox" }}, { "match": { "message": "brown fox" }} ], "tie_breaker": 0.3 } } }
在查询中算分过程如下如下:
1、取字段算分中的最高分
2、加上 tie_breaker 乘以其它匹配字段的 _score
most_fields
这种查询类型,返回的文档排序按照被查询字段匹配的越多排在越前面。
most_fields 查询方法如下:
GET /_search { "query": { "multi_match" : { "query": "quick brown fox", "type": "most_fields", "fields": [ "title", "title.original", "title.shingles" ] } } }
等同于:
GET /_search { "query": { "bool": { "should": [ { "match": { "title": "quick brown fox" }}, { "match": { "title.original": "quick brown fox" }}, { "match": { "title.shingles": "quick brown fox" }} ] } } }
最后算分将每个 match 子句的得分加在一起,然后除以 match 子句的数量。
注意:operator 和 minimum_should_match 条件是对 best_fields 和 most_fields 查询产生的每个查询子句的查询关系,而不会对查询字段进行 operator 的控制。
比如:
GET /_search { "query": { "multi_match" : { "query": "Will Smith", "type": "best_fields", "fields": [ "first_name", "last_name" ], "operator": "and" } } }
执行的效果则是 (+first_name:will +first_name:smith) | (+last_name:will +last_name:smith)的效果,即每个 match 查询的 and 关系。
phrase 和 phrase_prefix
在结果排序上的逻辑与 best_fields 一致,只是在查询方式上以 match_phrase 或者 match_phrase_prefix 的方式进行。
即,下面的查询:
GET /_search { "query": { "multi_match" : { "query": "quick brown f", "type": "phrase_prefix", "fields": [ "subject", "message" ] } } }
与这个查询是一样的:
GET /_search { "query": { "dis_max": { "queries": [ { "match_phrase_prefix": { "subject": "quick brown f" }}, { "match_phrase_prefix": { "message": "quick brown f" }} ] } } }
bool_prefix
在结果排序的逻辑与 most_fields 一致,但是查询使用的是 match_bool_prefix 而不是 match。即,下面的查询:
GET /_search { "query": { "multi_match" : { "query": "quick brown f", "type": "bool_prefix", "fields": [ "subject", "message" ] } } }
与这个查询类似:
GET /_search { "query": { "bool": { "should": [ { "match_phrase_prefix": { "subject": "quick brown f" }}, { "match_phrase_prefix": { "message": "quick brown f" }} ] } } }
最后算分将每个 match 子句的得分加在一起,然后除以 match 子句的数量。
cross_fields
将被查询的字段是为一个大字段,进行统一的分词并按照要求进行查询。
cross_fields 主要可以在查询时指定字段之间的关系,可以对词项在字段间的查询有更多的操控性,而不是统一默认的关系,甚至每个字段也并不一定需要满足才能返回文档。
比如下面的查询:
GET /_search { "query": { "multi_match" : { "query": "Will Smith", "type": "cross_fields", "fields": [ "first_name", "last_name" ], "operator": "and" } } }
查询逻辑更像是这样: (first_name:will OR last_name:will) + (first_name:smith OR last_name:smith),而两个字段并不一定都需要匹配 will 或者 smith,两个字段中有一个能匹配上文档就可以返回。
由于在 TF/IDF 算法中,词频是一个重要的影响因素,因此 cross_fields 能有有效消除词频在不同字段中的差距,解决了 best_fields 的词频差问题。
注意,cross_fields 通常只对 boost 为 1 的短字符串字段有用。除此之外,索引算法中词频和长度标准化也会对分数产生影响,从而导致 term 统计数据的混合不再有意义。cross_fields在分词器的处理上,只会将分词器相同的字段分组查询,然后对分组进行最高分比较。
比如,first 和 last 字段是相同的分词器,而 first.simple 和 last.simple 使用的是相同的分词器。
GET /_search { "query": { "multi_match" : { "query": "Jon", "type": "cross_fields", "fields": [ "first", "first.simple", "last", "last.simple" ] } } }
那么查询逻辑是这样的:
GET /_search { "query": { "dis_max": { "queries": [ { "multi_match" : { "query": "Jon", "type": "cross_fields", "fields": [ "first", "last" ] } }, { "multi_match" : { "query": "Jon", "type": "cross_fields", "fields": [ "first.simple","last.simple" ] } } ] } } }
关于 minimum_should_match:在多分词器分组的条件下,minimum_should_match 对分组的查询是对每个查询子项的统一化设置(即与 best_fields 一样的情况),所以有特殊的条件可以考虑分开重写。
注意:fuzziness 参数不可用于 cross_fields、phrase和 phrase_prefix 类型。
《Elastic Stack 实战手册》——三、产品能力——3.4.入门篇——3.4.2.Elasticsearch基础应用——3.4.2.17.Text analysis, settings 及 mappings——3.4.2.17.3.全文搜索/精确搜索(15) https://developer.aliyun.com/article/1229924