[Elasticsearch] 控制相关度 (五) - function_score查询及field_value_factor,boost_mode,max_mode参数 - dm_vincent的专栏 - 博客频道 - CSDN.NET

标签: elasticsearch 控制 相关 | 发表时间:2017-06-18 13:18 | 作者:
出处:http://blog.csdn.net

本章翻译自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。



相关 [elasticsearch 控制 相关] 推荐:

ElasticSearch 2 (18) - 深入搜索系列之控制相关度 - Richaaaard - 博客园

- -
ElasticSearch 2 (18) - 深入搜索系列之控制相关度. 处理结构化数据(比如:时间、数字、字符串、枚举)的数据库只需要检查一个文档(或行,在关系数据库)是否与查询匹配. 布尔是/非匹配是全文搜索的基础部分,但不止这些,我们也同样需要知道每个文档与查询的相关度,在全文搜索引擎中我们不仅需要找到匹配的文档,还需要根据他们相关度的高低,对他们进行排序.

Elasticsearch:什么是相关性

- - 翟志军
我们已经注意到,搜索结果会以相关性的倒序方式返回. 但是什么是相关性,它又是如何被计算出来的呢. 每一份被搜索出来的文档都带有一个由正的浮点数来表示的相关性评分,被称为_score. 这个分数越高,代表这份文档越相关. 查询子句会为每份文档生成一个评分_score. 如何生成这个评分依赖于查询子句的类型.

[Elasticsearch] 控制相关度 (五) - function_score查询及field_value_factor,boost_mode,max_mode参数 - dm_vincent的专栏 - 博客频道 - CSDN.NET

- -
本章翻译自Elasticsearch官方指南的Controlling Relevance一章. function_score查询. function_score查询是处理分值计算过程的终极工具. 它让你能够对所有匹配了主查询的每份文档调用一个函数来调整甚至是完全替换原来的_score. 实际上,你可以通过设置过滤器来将查询得到的结果分成若干个子集,然后对每个子集使用不同的函数.

控制Elasticsearch分片和副本的分配

- - 开源软件 - ITeye博客
ES集群中索引可能由多个分片构成,并且每个分片可以拥有多个副本. 通过将一个单独的索引分为多个分片,我们可以处理不能在一个单一的服务器上面运行的大型索引,简单的说就是索引的大小过大,导致效率问题. 不能运行的原因可能是内存也可能是存储. 由于每个分片可以有多个副本,通过将副本分配到多个服务器,可以提高查询的负载能力.

[译]elasticsearch mapping

- - an74520的专栏
es的mapping设置很关键,mapping设置不到位可能导致索引重建. 请看下面各个类型介绍^_^. 每一个JSON字段可以被映射到一个特定的核心类型. JSON本身已经为我们提供了一些输入,支持 string,  integer/ long,  float/ double,  boolean, and  null..

Elasticsearch as Database - taowen - SegmentFault

- -
【北京上地】滴滴出行基础平台部招聘 Elasticsearch 与 Mysql binlog databus 开发工程师. 内推简历投递给: taowen@didichuxing.com. 推销Elasticsearch. 时间序列数据库的秘密(1)—— 介绍. 时间序列数据库的秘密(2)——索引.

ElasticSearch 2 的节点调优(ElasticSearch性能)

- - 行业应用 - ITeye博客
一个ElasticSearch集群需要多少个节点很难用一种明确的方式回答,但是,我们可以将问题细化成一下几个,以便帮助我们更好的了解,如何去设计ElasticSearch节点的数目:. 打算建立多少索引,支持多少应用. elasticsearch版本: elasticsearch-2.x. 需要回答的问题远不止以上这些,但是第五个问题往往是容易被我们忽视的,因为单个ElasticSearch集群有能力支持多索引,也就能支持多个不同应用的使用.

elasticsearch的javaAPI之query

- - CSDN博客云计算推荐文章
elasticsearch的javaAPI之query API. the Search API允许执行一个搜索查询,返回一个与查询匹配的结果(hits). 它可以在跨一个或多个index上执行, 或者一个或多个types. 查询可以使用提供的 query Java API 或filter Java API.

Elasticsearch基础教程

- - 开源软件 - ITeye博客
转自:http://blog.csdn.net/cnweike/article/details/33736429.     Elasticsearch有几个核心概念. 从一开始理解这些概念会对整个学习过程有莫大的帮助.     接近实时(NRT).         Elasticsearch是一个接近实时的搜索平台.

ElasticSearch索引优化

- - 行业应用 - ITeye博客
ES索引的过程到相对Lucene的索引过程多了分布式数据的扩展,而这ES主要是用tranlog进行各节点之间的数据平衡. 所以从上我可以通过索引的settings进行第一优化:. 这两个参数第一是到tranlog数据达到多少条进行平衡,默认为5000,而这个过程相对而言是比较浪费时间和资源的. 所以我们可以将这个值调大一些还是设为-1关闭,进而手动进行tranlog平衡.