[Elasticsearch] 控制相关度 (五) - function_score查询及field_value_factor,boost_mode,max_

news/2024/7/1 23:58:45

本章翻译自Elasticsearch官方指南的Controlling Relevance一章。

 

 

function_score查询

function_score查询是处理分值计算过程的终极工具。它让你能够对所有匹配了主查询的每份文档调用一个函数来调整甚至是完全替换原来的_score。

实际上,你可以通过设置过滤器来将查询得到的结果分成若干个子集,然后对每个子集使用不同的函数。这样你就能够同时得益于:高效的分值计算以及可缓存的过滤器。

它拥有几种预先定义好了的函数:

weight

对每份文档适用一个简单的提升,且该提升不会被归约:当weight为2时,结果为2 * _score。

field_value_factor

使用文档中某个字段的值来改变_score,比如将受欢迎程度或者投票数量考虑在内。

random_score

使用一致性随机分值计算来对每个用户采用不同的结果排序方式,对相同用户仍然使用相同的排序方式。

衰减函数(Decay Function) - linear,exp,gauss

将像publish_date,geo_location或者price这类浮动值考虑到_score中,偏好最近发布的文档,邻近于某个地理位置(译注:其中的某个字段)的文档或者价格(译注:其中的某个字段)靠近某一点的文档。

script_score

使用自定义的脚本来完全控制分值计算逻辑。如果你需要以上预定义函数之外的功能,可以根据需要通过脚本进行实现。

没有function_score查询的话,我们也许就不能将全文搜索得到分值和近因进行结合了。我们将不得不根据_score或者date进行排序;无论采用哪一种都会抹去另一种的影响。function_score查询让我们能够将两者融合在一起:仍然通过全文相关度排序,但是给新近发布的文档,或者流行的文档,或者符合用户价格期望的文档额外的权重。你可以想象,一个拥有所有这些功能的查询看起来会相当复杂。我们从一个简单的例子开始,循序渐进地对它进行介绍。

 

 

根据人气来提升(Boosting by Popularity)

假设我们有一个博客网站让用户投票选择他们喜欢的文章。我们希望让人气高的文章出现在结果列表的头部,但是主要的排序依据仍然是全文搜索分值。我们可以通过保存每篇文章的投票数量来实现:

PUT /blogposts/post/1
{
  "title":   "About popularity",
  "content": "In this post we will talk about...",
  "votes":   6
}

在搜索期间,使用带有field_value_factor函数的function_score查询将投票数和全文相关度分值结合起来:

GET /blogposts/post/_search
{
  "query": {
    "function_score": { 
      "query": { 
        "multi_match": {
          "query":    "popularity",
          "fields": [ "title", "content" ]
        }
      },
      "field_value_factor": { 
        "field": "votes" 
      }
    }
  }
}

function_score查询会包含主查询(Main Query)和希望适用的函数。先会执行主查询,然后再为匹配的文档调用相应的函数。每份文档中都必须有一个votes字段用来保证function_score能够起作用。

在前面的例子中,每份文档的最终_score会通过下面的方式改变:

new_score = old_score * number_of_votes

它得到的结果并不好。全文搜索的_score通常会在0到10之间。而从下图我们可以发现,拥有10票的文章的分值大大超过了这个范围,而没有被投票的文章的分值会被重置为0。

modifier

为了让votes值对最终分值的影响更缓和,我们可以使用modifier。换言之,我们需要让头几票的效果更明显,其后的票的影响逐渐减小。0票和1票的区别应该比10票和11票的区别要大的多。

一个用于此场景的典型modifier是log1p,它将公式改成这样:

new_score = old_score * log(1 + number_of_votes)

log函数将votes字段的效果减缓了,其效果类似下面的曲线:

使用了modifier参数的请求如下:

GET /blogposts/post/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query":    "popularity",
          "fields": [ "title", "content" ]
        }
      },
      "field_value_factor": {
        "field":    "votes",
        "modifier": "log1p" 
      }
    }
  }
}

可用的modifiers有:none(默认值),log,log1p,log2p,ln,ln1p,ln2p,square,sqrt以及reciprocal。它们的详细功能和用法可以参考field_value_factor文档。

factor

可以通过将votes字段的值乘以某个数值来增加该字段的影响力,这个数值被称为factor:

GET /blogposts/post/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query":    "popularity",
          "fields": [ "title", "content" ]
        }
      },
      "field_value_factor": {
        "field":    "votes",
        "modifier": "log1p",
        "factor":   2 
      }
    }
  }
}

添加了factor将公式修改成这样:

new_score = old_score * log(1 + factor * number_of_votes)

当factor大于1时,会增加其影响力,而小于1的factor则相应减小了其影响力,如下图所示:

boost_mode

将全文搜索的相关度分值乘以field_value_factor函数的结果,对最终分值的影响可能太大了。通过boost_mode参数,我们可以控制函数的结果应该如何与_score结合在一起,该参数接受下面的值:

  • multiply:_score乘以函数结果(默认情况)
  • sum:_score加上函数结果
  • min:_score和函数结果的较小值
  • max:_score和函数结果的较大值
  • replace:将_score替换成函数结果

如果我们是通过将函数结果累加来得到_score,其影响会小的多,特别是当我们使用了一个较低的factor时:

GET /blogposts/post/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query":    "popularity",
          "fields": [ "title", "content" ]
        }
      },
      "field_value_factor": {
        "field":    "votes",
        "modifier": "log1p",
        "factor":   0.1
      },
      "boost_mode": "sum" 
    }
  }
}

上述请求的公式如下所示:

new_score = old_score + log(1 + 0.1 * number_of_votes)

max_boost

最后,我们能够通过制定max_boost参数来限制函数的最大影响:

GET /blogposts/post/_search
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query":    "popularity",
          "fields": [ "title", "content" ]
        }
      },
      "field_value_factor": {
        "field":    "votes",
        "modifier": "log1p",
        "factor":   0.1
      },
      "boost_mode": "sum",
      "max_boost":  1.5 
    }
  }
}

无论field_value_factor函数的结果是多少,它绝不会大于1.5。

NOTE

max_boost只是对函数的结果有所限制,并不是最终的_score。

http://blog.csdn.net/dm_vincent/article/details/42201721


http://www.niftyadmin.cn/n/3301283.html

相关文章

Delphi利用Windows GDI实现文字倾斜

Delphi利用Windows GDI实现文字倾斜摘要 Delphi利用Windows GDI实现文字倾斜procedure TForm1.FormPaint(Sender: TObject);var FLogFont: tagLogFontW; hTempFont, hPrevFont: HFONT; //字体句柄 hTempDC: HDC; //设备描述表或图形设备句柄 TempString: string; //输出的文…

CodeForces 631 A.Interview(水~)

Description f(x,l,r)表示将x序列的第l个元素到第r个元素按位或后的结果&#xff0c;给出两个长度为n的序列&#xff0c;问f(a,l,r)f(b,l,r)的最大值&#xff0c;1<l<r<n Input 第一行一整数n表示序列长度&#xff0c;之后输入两个长度为n的序列a和b(0<ai,bi<…

Python学习笔记(一)——输入与输出

输出&#xff1a;——print() Python中的输出使用print()完成 >>> 在屏幕中输出Hello World >>> print(Hello World) Hello World使用print()函数输出多个字符串时要使用逗号隔开 >>> print(hello,everyone,this,is,GUN) hello everyone this is GU…

ElasticSearch中设置排序Java

有用的链接:http://stackoverflow.com/questions/12215380/sorting-on-several-fields-in-elasticsearch 有的时候,需要自己设定排序,java的一个接口如下: String time1 ConstValue.GetCurrentDate();SortBuilder sortBuilder SortBuilders.fieldSort("tfp_save_time&qu…

C++如何判断某一文件是否存在

函数名: access功 能: 确定文件的访问权限用 法: int access(const char *filename, int amode);程序例:#include <stdio.h>#include <io.h>int file_exists(char *filename);int main(void){printf("Does NOTEXIST.FIL exist: %s\n",file_exists("…

CodeForces 631 B.Print Check(水~)

Description 给出一个n*m的网格图&#xff0c;起初所有格子颜色都是0&#xff0c;之后k次操作&#xff0c;每次把某一行或某一列涂成某种颜色&#xff0c;要求输出操作完后所有格子的颜色 Input 第一行三个整数n,m,k分别表示网格图的规模和操作数&#xff0c;之后k行每行三个…

VC++ MFC文件的移动复制删除更名遍历操作

1&#xff0e;判断文件是否存在利用CFile类和CFileStatus类判断CFileStatus filestatus;if (CFile::GetStatus(_T("d://softist.txt"), filestatus))AfxMessageBox(_T("文件存在"));elseAfxMessageBox(_T("文件不存在"));利用CFileFind类判断CFi…

为ElasticSearch添加HTTP基本认证

ES的HTTP连接没有提供任何的权限控制措施&#xff0c;一旦部署在公共网络就容易有数据泄露的风险&#xff0c;尤其是加上类似elasticsearch-head这样友好的前端界面&#xff0c;简直让你的数据瞬间裸奔在黑客的眼皮底下。项目上线前做十万伏特的防护当然不现实&#xff0c;但至…