25、ElasticSearch 7.x 近似匹配、混合使用ma
主要内容:近似匹配、混合使用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
}
}
}
}
}
}