zoukankan      html  css  js  c++  java
  • Elasticsearch学习之深入搜索六 --- 平衡搜索结果的精准率和召回率

    1. 召回率和精准度

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

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

    直接用match_phrase短语搜索,会导致必须所有term都在doc field中出现,而且距离在slop限定范围内,才能匹配上

    match phrase,proximity match,要求doc必须包含所有的term,才能作为结果返回;如果某一个doc可能就是有某个term没有包含,那么就无法作为结果返回

    java spark --> hello world java --> 就不能返回了
    java spark --> hello world, java spark --> 才可以返回

      近似匹配的时候,召回率比较低,精准度太高了,但是有时可能我们希望的是匹配到几个term中的部分,就可以作为结果出来,这样可以提高召回率。同时我们也希望用上match_phrase根据距离提升分数的功能,让几个term距离越近分数就越高,优先返回,就是优先满足召回率的意思,java spark,包含java的也返回,包含spark的也返回,包含java和spark的也返回;同时兼顾精准度,就是包含java和spark,同时java和spark离的越近的doc排在最前面,此时可以用bool组合match query和match_phrase query一起,来实现上述效果

    GET /forum/article/_search
    {
      "query": {
        "bool": {
          "must": {
            "match": { 
              "title": {
                "query": "java spark" --> java或spark或java spark,java和spark靠前,但是没法区分java和spark的距离,也许java和spark靠的很近,但是没法排在最前面
              }
            }
          },
          "should": {
            "match_phrase": { --> 在slop以内,如果java spark能匹配上一个doc,那么就会对doc贡献自己的relevance score,如果java和spark靠的越近,那么就分数越高
              "title": {
                "query": "java spark",
                "slop":  50
              }
            }
          }
        }
      }
    }
    
    GET /forum/article/_search 
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "content": "java spark"
              }
            }
          ]
        }
      }
    }

    2. 优化近似匹配的性能

      match query的性能比phrase match和proximity match(有slop)要高很多。因为后两者都要计算position的距离。
    match query比phrase match的性能要高10倍,比proximity match的性能要高20倍。优化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都去进行计算和贡献分数

    rescore:重打分

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

    GET /forum/article/_search 
    {
      "query": {
        "match": {
          "content": "java spark"
        }
      },
      "rescore": {
        "window_size": 50,
        "query": {
          "rescore_query": {
            "match_phrase": {
              "content": {
                "query": "java spark",
                "slop": 50
              }
            }
          }
        }
      }
    }
  • 相关阅读:
    牛客网 剑指Offer JZ19 顺时针打印矩阵
    牛客网 剑指Offer Z18 二叉树的镜像
    牛客网 剑指Offer JZ17 树的子结构
    一键安装脚本(MySQL双主、EMQX集群、FastDFS集群)
    API和拦截器相关的设计简记
    C# 获取今天,昨天,上周,下周,上月,下月等等一些日期格式
    Element.scrollIntoView()
    自主学习(1)--matlab
    四则运算java
    学习计划
  • 原文地址:https://www.cnblogs.com/sunfie/p/7109859.html
Copyright © 2011-2022 走看看