ElasticSearch实战笔记

25、ElasticSearch 7.x 近似匹配、混合使用ma

2020-04-09  本文已影响0人  众神开挂

主要内容:近似匹配、混合使用match和近似匹配、rescoring机制

1、近似匹配

1.1、match_phrase 短语查询

phrase match,就是要去将多个term作为一个短语,一起去搜索,只有包含这个短语的doc才会作为结果返回。

match_phrase语法

//将一个doc的content设置为恰巧包含java spark这个短语.
GET /forum/_search
{
  "query": {
    "match_phrase": {
      "content": "java spark"
    }
  }
}

只有包含java spark这个短语的doc才返回了,只包含java的doc不会返回

1.2、 基于slop参数实现近似匹配

实战演练

GET /forum/_search
{
  "query": {
    "match_phrase": {
      "title": {
        "query": "elasticsearch hadoop",
        "slop": 1
      }
    }
  }
}

slop的含义是什么?

slop的含义,:一个query string terms,最多可以移动几次去尝试跟一个doc匹配上

实验验证slop的含义

GET /forum/_search
{
  "query": {
    "match_phrase": {
      "title": {
        "query": "java spark",
        "slop": 3
      }
    }
  }
}

<u>spark</u> is best big <u>data</u>

spark data(data右移三次才会匹配)

案例02:

data spark 匹配 spark is best big data

data(右移四次)+spark(左移一次)=共5次

GET /forum/_search
{
  "query": {
    "match_phrase": {
      "content": {
        "query": "data spark",
        "slop": 5
      }
    }
  }
}

slop搜索下,关键词离的越近,relevance score就会越高。

加了slop的phrase match,就是proximity match,近似匹配

2、混合使用match和近似匹配实现召回率与精准度的平衡

召回率 recall 与 精准度 precision的基本概念:

比如你搜索一个java spark,总共有100个doc,能返回多少个doc作为结果,就是召回率

比如你搜索一个java spark,能不能尽可能让包含java spark,或者是java和spark离的很近的doc,排在最前面,这就是精准度。

近似匹配的时候,召回率比较低,精准度太高了

但是有时可能我们希望的是匹配到几个term中的部分,就可以作为结果出来,这样可以提高召回率。同时我们也希望用上match_phrase根据距离提升分数的功能,让几个term距离越近分数就越高,优先返回

就是优先满足召回率,意思,java spark,包含java的也返回,包含spark的也返回,包含java和spark的也返回;同时兼顾精准度,就是包含java和spark,同时java和spark离的越近的doc排在最前面

此时可以用bool组合match query和match_phrase query一起,来实现上述效果

GET /forum/_search
{
  "query": {
    "bool": {
      "must": {
        "match": {
          "title": {
            "query": "java spark" #返回所有java spark的结果,但不能区分java和spark的距离
          }
        }
      },
      "should": {
        "match_phrase": {
          "title": {
            "query": "java spark", #在slop以内,增加匹配doc的relevance score
            "slop": 50
          }
        }
      }
    }
  }
}

查询示例02:

GET /forum/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "content": "java spark"
          }
        }
      ],
      "should": [
        {
          "match_phrase": {
            "content": {
              "query": "java spark",
              "slop": 50
            }
          }
        }
      ]
    }
  }
}

3、使用rescoring机制优化近似匹配搜索的性能

3.1、match和phrase match(proximity match)

match query的性能比phrase match和proximity match(有slop)要高很多。因为后两者都要计算position的距离。
match query比phrase match的性能要高10倍,比proximity match的性能要高20倍。

但是别太担心,因为es的性能一般都在毫秒级别,match query一般就在几毫秒,或者几十毫秒,而phrase match和proximity match的性能在几十毫秒到几百毫秒之间,所以也是可以接受的。

优化proximity match的性能,一般就是减少要进行proximity match搜索的document数量。主要思路就是,用match query先过滤出需要的数据,然后再用proximity match来根据term距离提高doc的分数,同时proximity match只针对每个shard的分数排名前n个doc起作用,来重新调整它们的分数,这个过程称之为rescoring(重打分),重计分。因为一般用户会分页查询,只会看到前几页的数据,所以不需要对所有结果进行proximity match操作。

用我们刚才的说法,match + proximity match同时实现召回率和精准度

默认情况下,match也许匹配了1000个doc,proximity match全都需要对每个doc进行一遍运算,判断能否slop移动匹配上,然后去贡献自己的分数
但是很多情况下,match出来也许1000个doc,其实用户大部分情况下是分页查询的,所以可能最多只会看前几页,比如一页是10条,最多也许就看5页,就是50条
proximity match只要对前50个doc进行slop移动去匹配,去贡献自己的分数即可,不需要对全部1000个doc都去a进行计算和贡献分数

match:1000个doc,其实这时候每个doc都有一个分数了; proximity match,前50个doc,进行rescore,重打分,即可; 让前50个doc,term举例越近的,排在越前面

GET /forum/_search
{
  "query": {
    "match": {
      "content": "java spark"
    }
  },
  "rescore": {
    "window_size": 50,  ##对前50个打分
    "query": {
      "rescore_query": {
        "match_phrase": {
          "content": {
            "query": "java spark",
            "slop": 50
          }
        }
      }
    }
  }
}
上一篇下一篇

猜你喜欢

热点阅读