multi_match多field检索详解

一、相关度分数

计算每个document的(相关度分数)relevance score:每个query的分数,乘以matched query数量,除以总query数量

比如查询语句如下

{
    "query": {
        "bool": {
            "should": [
                { "match": { "title": "java solution" }},
                { "match": { "content":  "java solution" }}
            ]
        }
    }
}

在查询出的每个文档计算相关度分数流程:

1、针对某个document算出符合每个条件的相关度分数

       匹配条件:{ "match": { "title": "java solution" }},如果匹配上会是有一个分数,匹配不上即分数为0,假定分数表示为F1
       匹配条件:{ "match": { "content":  "java solution" }},如果匹配上会是有一个分数,匹配不上即分数为0,假定分数表示F2

2、计算document相关度分数

matched query数量为M,总query数量为T

最终document相关度分数=(F1+F2)*M/T

例:doc1检索都匹配到了should里的两个match query则M为2  T是match query的总数也是2

       doc2检索时只匹配了一个match query则M为1,T还是2

 

二、检索策略

1、best fields策略(默认)

某一个field中匹配到了尽可能多的关键词,被排在前面;而不是尽可能多的field匹配到了少数的关键词,排在了前面。

best fields底层使用dis_max语法,直接取多个query中,分数最高的那一个query的分数即可用上面查询说明,如果F1>F2,则document的相关度分数即为F1

GET /forum/_search
{
  "query": {
    "dis_max": {
      "queries": [
        {"match": { "title": "java solution" }},
        { "match": { "content":  "java solution" }}
        ]
    }
  }
}

注意:

dis_max只取某一个query最大的分数,完全不考虑其他query的分数,此时可以使用tie_breaker将其他query的分数也考虑进去。

除了最高query分数外,将其他query的分数,乘以tie_breaker,然后综合与最高分数的那个query的分数,综合在一起进行计算。所以除了取最高分以外,还会考虑其他的query的分数,tie_breaker的值,在0~1之间

GET /forum/_search
{
  "query": {
    "dis_max": {
      "tie_breaker": 0.7,
      "boost": 1.2,
      "queries": [
        {"match": { "title": "java solution" }},
        { "match": { "content":  "java solution" }}
        ]
    }
  }
}

上面的写法有点繁琐:es提供了简便写法

GET /forum/_search
{
  "query": {
    "multi_match": {
        "query":                "java solution",
        "type":                 "best_fields", 
        "fields":               [ "title", "content" ],
        "tie_breaker":          0.3,
        "minimum_should_match": "50%"   
    }
  } 
}

minimum_should_match:比如你搜索5个关键词,但是很多结果是只匹配1个关键词的,其实跟你想要的结果相差甚远,这些结果就是长尾,minimum_should_match,控制搜索结果的精准度,只有匹配一定数量的关键词的数据,才能返回。

优点:通过best_fields策略,以及综合考虑其他field,还有minimum_should_match支持,可以尽可能精准地将匹配的结果推送到最前面
缺点:除了那些精准匹配的结果,其他差不多大的结果,排序结果不是太均匀,没有什么区分度了

比如:百度之类的搜索引擎,最匹配的到最前面,但是其他的就没什么区分度了

2、most-fields策略

尽可能返回更多field匹配到某个关键词的doc,优先返回回来

综合多个field一起进行搜索,尽可能多地让所有field的query参与到总分数的计算中来,此时就会是个大杂烩,出现类似best_fields案例最开始的那个结果,结果不一定精准,某一个document的一个field包含更多的关键字,但是因为其他document有更多field匹配到了,所以排在了前面;所以需要建立类似sub_title.std这样的field,尽可能让某一个field精准匹配query string,贡献更高的分数,将更精准匹配的数据排到前面。

优点:将尽可能匹配更多field的结果推送到最前面,整个排序结果是比较均匀的
缺点:

(1)可能那些精准匹配的结果,无法推送到最前面

(2)只是找到尽可能多的field匹配的doc,而不是某个field完全匹配的doc

(3)不能用minimum_should_match去掉长尾数据,就是匹配的特别少的结果

比如:wiki,明显的most_fields策略,搜索结果比较均匀,但是的确要翻好几页才能找到最匹配的结果

举例:

POST /forum/_mapping
{
  "properties": {
      "sub_title": { 
          "type":     "string",
          "analyzer": "english",
          "fields": {
              "std":   { 
                  "type":     "string",
                  "analyzer": "standard"
              }
          }
      }
  }
}

POST /forum/_bulk
{ "update": { "_id": "1"} }
{ "doc" : {"sub_title" : "learning more courses"} }
{ "update": { "_id": "2"} }
{ "doc" : {"sub_title" : "learned a lot of course"} }
{ "update": { "_id": "3"} }
{ "doc" : {"sub_title" : "we have a lot of fun"} }
{ "update": { "_id": "4"} }
{ "doc" : {"sub_title" : "both of them are good"} }
{ "update": { "_id": "5"} }
{ "doc" : {"sub_title" : "haha, hello world"} }

使用most-fields策略检索

GET /forum/_search
{
   "query": {
        "multi_match": {
            "query":  "learning courses",
            "type":   "most_fields", 
            "fields": [ "sub_title", "sub_title.std" ]
        }
    }
}

基于most-fields的检索弊端可以可以使用:copy_to将多个field组合成一个field

比如我们想在author_first_name和author_last_name匹配一个人名的话,

PUT /forum/_mapping/
{
  "properties": {
      "author_first_name": {
          "type":     "string",
          "copy_to":  "new_author_full_name" 
      },
      "author_last_name": {
          "type":     "string",
          "copy_to":  "new_author_full_name" 
      },
      "new_author_full_name": {
          "type":     "string"
      }
  }
}

因为建了mapping,就可以将多个字段的值拷贝到一个字段中,并建立倒排索引,使用new_author_full_name一个字段使用best fields也可以匹配

3、cross-fields策略

检索的关键字在match中多个fields中出现过,且cross-fields支持 minimum_should_match

GET /forum/_search
{
  "query": {
    "multi_match": {
      "query": "Peter Smith",
      "type": "cross_fields", 
      "operator": "and",
      "fields": ["author_first_name", "author_last_name"]
    }
  }
}

 

你可能感兴趣的:(ElasticSearch,elasticsearch)