ElasticSearch function_score()二次评分

说明

有时,在 做全文检索时,需要对 es 的评分进行二次评分

应用场景

如:对标题进行查询时,除了本身的得分,对于平台来说,还有个性化需求:文章点赞数量越多,得分就越高,类似抖音平台,点赞量越高,就越给流量。类似百度,竞价越高,排名越靠前。对于 ES 来说,就是 二次评分

原分值:

GET /toutiao_v1/_search
{
  "query": {
    "match": {
      "title": "java"
    }
  },
  "_source": [
    "title",
    "like"
  ]
}

function_score()

可进行二次评分

  • field_value_factor : 将某个字段的值乘上 score

field_value_factor

例子

计算方式:new_score=old_score * 字段值

GET /toutiao_v1/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "java"
        }
      },
      "field_value_factor": {
        "field": "like"        //评分 乘以 like字段的值
      }
    }
  },
  "_source": [
    "title",
    "like"
  ]
}

执行结果:

缺点

如果 like 特别大,那么分值就特别大,反之亦然。like 的大小,完全影响 分值,match 匹配查询的影响过低。

这是不合理的,因为,完全受 like 点赞量影响,查询条件影响过低,导致查询结果并不是用户想要的内容

解决方式:log1p

为了解决 分值过大、过小,使用 log1p,即:new_score=old_score * log(1 + 字段值)

注意: 以 10 为底

这样不会过大过小

GET /toutiao_v1/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "java"
        }
      },
      "field_value_factor": {
        "field": "like",
        "modifier": "log1p"
      }
    }
  }
}

执行结果:

like 会影响二次评分,但不会起决定性的作用

解决方式:factor

设置 字段值的权重,即:new_score=old_score * log(1 + factor * 字段值)

GET /toutiao_v1/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "java"
        }
      },
      "field_value_factor": {
        "field": "like",
        "modifier": "log1p",
        "factor": 0.1
      }
    }
  }
}

boost_mode

boost_mode : 决定 old_score 和 加强 score 如何合并

  • multiply(默认) : new_score = old_score * 加强score

  • sum : new_score = old_score + 加强score

  • min : old_score 和 加强score 取较小值,new_score = min(old_score, 加强score)

  • max : old_score 和 加强score 取较大值,new_score = max(old_score, 加强score)

  • replace : 加强score直接替换掉old_score,new_score = 加强score

GET /toutiao_v1/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "java"
        }
      },
      "field_value_factor": {
        "field": "like"
      },
      "boost_mode": "sum" // newScore=like+old_score
    }
  }
}

max_boost

限制加强函数的最大效果,就是 限制加强score最大能多少,但要注意不会限制old_score

如果加强score超过了max_boost限制的值,会把加强score的值设成max_boost的值

假设加强score是5,而max_boost是2,因为加强score超出了max_boost的限制,所以max_boost就会把加强score改为2

GET /toutiao_v1/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "title": "java"
        }
      },
      "field_value_factor": {
        "field": "like"
      },
      "max_boost": 0.5 // 为了演示效果,如果 like 大于0.5,那么取值0.5
    }
  }
}

注意

不要执著在调整function_score上

文档相关度的调整非常玄,”最相关的文档” 是一个难以触及的模糊概念,每个人对文档排序有著不同的想法,这很容易使人陷入持续反覆调整,但是确没有明显的进展

为了避免跳入这种死循环,在调整function_score时,一定要搭配监控用户操作,才有意义

像是如果返回的文档是用户想要的高相关的文档,那麽用户就会选择前10个中的一个文档,得到想要的结果,反之,用户可能会来回点击,或是尝试新的搜索条件

一旦有了这些监控手段,想要调适完美的function_score就不是问题

因此调整function_score的重点在于,要透过监控用户、和用户互动,慢慢去调整我们的搜索条件,而不要妄想一步登天,第一次就把文档的相关度调整到最好,这几乎是不可能的,因为,连用户自己也不知道他自己想要什麽

感谢:
https://blog.csdn.net/weixin_40341116/article/details/80913045


原文出处:/show_1IX1sHrb7Yjf.html