前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Function score查询的应用及源码解析

Function score查询的应用及源码解析

作者头像
用户7634691
发布2021-02-03 12:04:21
7870
发布2021-02-03 12:04:21
举报

概念介绍

function_score查询可以在原有的查询结果算分的基础上,对每个文档计算一个新的算分,而计算的规则取决于应用的具体的funcion以及相关的一些选项。

看一个例子,

代码语言:javascript
复制
GET kibana_sample_data_ecommerce/_search?
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "manufacturer": "Elitelligence"
        }
      },
      "boost": "5",
      "weight": 2,
      "boost_mode": "multiply"
    }
  }
}

上面这个查询,它的执行过程是这样的,首先执行查询

代码语言:javascript
复制
GET kibana_sample_data_ecommerce/_search?
{
  "query": {
    "match": {
      "manufacturer": "Elitelligence"
    }
  }
}

比如某个文档查询处理算分是1.6829565,function指定的函数是weight,ES默认会用这个值乘以当前的算分,然后因为boost的值是5,并且boost_mode指定的计算方法是multiply,所以最终的算分是:

代码语言:javascript
复制
1.6829565 * 2 * 5 = 16.829565

boost_mode : 决定 old_score 和 加强score 如何合併。score_mode : 决定functions裡面的加强score们怎麽合併,会先合併加强score们成一个总加强score,再使用总加强score去和old_score做合併,换言之就是会先执行score_mode,再执行boost_mode。

boost_mode除了multiply还有一些其它的选项,比如max,sum等,具体可以看官方文档。而function除了weight之外,还有script_score, random_scorefield_value_factordecay functions等,下个章节讲应用场景会有一些涉及到。

一些应用的场景

比如CSDN博客网站,在站内搜索博客时,产品经理可能希望除了基本的相关度之外,把博客点赞数较高的相对排名较高。这就是希望点赞数影响进本的搜索算分。就是一个function sorce典型的应用场景。

插入一些测试数据,

代码语言:javascript
复制
PUT /blogs/_doc/2
{
  "content": "We like elasticsearch",
  "votes":   2
}


GET blogs/_search
{
  "query": {
    "match": {
      "content": "elasticsearch"
    }
  }
}

正常情况下,如果我们执行下面这个查询语句

代码语言:javascript
复制
GET blogs/_search
{
  "query": {
    "match": {
      "content": "elasticsearch"
    }
  }
}

显然文档2的评分会更高,因为文档2更短,如果我们使用function score查询,

代码语言:javascript
复制
GET blogs/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content": "elasticsearch"
        }
      },
      "field_value_factor": {
        "field": "likes",
        "factor": 2,
        "modifier": "sqrt",
        "missing": 1
      }
    }
  }
}

结果是文档1的评分更高了,原因在于field_value_factor这个funcion会执行下面的规则计算一个得分,然后乘以原始的算分。

代码语言:javascript
复制
sqrt(2 * doc['likes'].value)

其中的modifier还可以是其它的数学公式,比如log,详细的可以参考官方文档。missing的意思是说,如果某个文档的likes字段是空的,就默认它的值是1。

同样的例子,比如有一个商品索引,搜索时希望在相关度排序的基础上,销量(sales)更高的商品能排在靠前的位置,也是类似的方案实现。

再说一个应用场景,比如网站的广告,为了提高展示率,希望广告能随机展示出来,不然就总是展示某几个算分高的。但是可能又希望同一个用户看到的广告排名是一致的。这种场景,random_score就排上用场了,我们可以使用用户id作为随机的seed。

查询语句类似如下:

代码语言:javascript
复制

GET kibana_sample_data_ecommerce/_search?
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "manufacturer": "优衣库"
        }
      },
      "random_score": {
        "seed": "userid"
      }
    }
  }
}

源码层面的分析

源码版本基于ES7.10

function score的核心处理类是AFunctionScoreQuery类,这个类的生成是在FunctionScoreQueryBuilder,如下图所示:

FunctionScoreQueryBuilder.java

我们基于一个具体的查询示例来分析源码:

代码语言:javascript
复制
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "content": "elasticsearch"
        }
      },
      "field_value_factor": {
        "field": "likes",
        "factor": 2,
        "modifier": "sqrt",
        "missing": 1
      }
    }
  }
}

基于我们上面的示例,这里调用第2个构造函数,因为我们这里只有一个function,boostMode没有指定,用的是默认的multiply。minScore是设置一个最低算分的阈值,就是结果不能低于这个,没有指定默认是null。maxBoost是最高算分的阈值,没有指定的话默认是FLT_MAX。

代码语言:javascript
复制
FLT_MAX的定义则是
#define FLT_MAX 3.402823466e+38F

Luncene的算分(score),Weight类是Search过程中很重要的类,它负责生成Scorer,这是一个所有命中文档的迭代器,IndexSearch类调用的createWeight最终会调用到实际的Query(这里就是FunctionScoreQuery)中的方法,

FunctionScoreQuery.java

拿到Weight类之后,上层通用的流程会创建Scorer(本示例中是FunctionFactorScorer),然后遍历符合条件的文档计算算分(score方法)。

FunctionScoreQuery.java

上面中,factor是最终要和原始算分相乘(默认是相乘)的计算因子。这个因子是怎么算出来的呢?计算规则是调用了FieldValueFactorFunction类的score方法。

FieldValueFactorFunction.java

看到这里,你应该已经看出来了,这里最终的算分就是

代码语言:javascript
复制
sqrt(2 * doc['likes'].value) * 原始算分
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 犀牛的技术笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概念介绍
  • 一些应用的场景
  • 源码层面的分析
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档