最佳字段(Best Fields)

假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样:

PUT /my_index/my_type/1
{
"title": "Quick brown rabbits",
"body": "Brown rabbits are commonly seen."
} PUT /my_index/my_type/2
{
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}

用户输入了"Brown fox",然后按下了搜索键。我们无法预先知道用户搜索的词条会出现在博文的title或者body字段中,但是用户是在搜索和他输入的单词相关的内容。以上的两份文档中,文档2似乎匹配的更好一些,因为它包含了用户寻找的两个单词。

让我们运行下面的bool查询:

{
"query": {
"bool": {
"should": [
{ "match": { "title": "Brown fox" }},
{ "match": { "body": "Brown fox" }}
]
}
}
}

然后我们发现文档1的分值更高:

{
"hits": [
{
"_id": "1",
"_score": 0.14809652,
"_source": {
"title": "Quick brown rabbits",
"body": "Brown rabbits are commonly seen."
}
},
{
"_id": "2",
"_score": 0.09256032,
"_source": {
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}
}
]
}

要理解原因,想想bool查询是如何计算得到其分值的:

  1. 运行should子句中的两个查询
  2. 相加查询返回的分值
  3. 将相加得到的分值乘以匹配的查询子句的数量
  4. 除以总的查询子句的数量

文档1在两个字段中都包含了brown,因此两个match查询都匹配成功并拥有了一个分值。文档2在body字段中包含了brown以及fox,但是在title字段中没有出现任何搜索的单词。因此对body字段查询得到的高分加上对title字段查询得到的零分,然后在乘以匹配的查询子句数量1,最后除以总的查询子句数量2,导致整体分值比文档1的低。

在这个例子中,titlebody字段是互相竞争的。我们想要找到一个最佳匹配(Best-matching)的字段。

如果我们不是合并来自每个字段的分值,而是使用最佳匹配字段的分值作为整个查询的整体分值呢?这就会让包含有我们寻找的两个单词的字段有更高的权重,而不是在不同的字段中重复出现的相同单词。

dis_max查询

相比使用bool查询,我们可以使用dis_max查询(Disjuction Max Query)。Disjuction的意思"OR"(而Conjunction的意思是"AND"),因此Disjuction Max Query的意思就是返回匹配了任何查询的文档,并且分值是产生了最佳匹配的查询所对应的分值:

{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Brown fox" }},
{ "match": { "body": "Brown fox" }}
]
}
}
}

它会产生我们期望的结果:

{
"hits": [
{
"_id": "2",
"_score": 0.21509302,
"_source": {
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}
},
{
"_id": "1",
"_score": 0.12713557,
"_source": {
"title": "Quick brown rabbits",
"body": "Brown rabbits are commonly seen."
}
}
]
}

最佳字段查询的调优

如果用户搜索的是"quick pets",那么会发生什么呢?两份文档都包含了单词quick,但是只有文档2包含了单词pets。两份文档都没能在一个字段中同时包含搜索的两个单词。

一个像下面那样的简单dis_max查询会选择出拥有最佳匹配字段的查询子句,而忽略其他的查询子句:

{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Quick pets" }},
{ "match": { "body": "Quick pets" }}
]
}
}
}
{
"hits": [
{
"_id": "1",
"_score": 0.12713557,
"_source": {
"title": "Quick brown rabbits",
"body": "Brown rabbits are commonly seen."
}
},
{
"_id": "2",
"_score": 0.12713557,
"_source": {
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}
}
]
}

可以发现,两份文档的分值是一模一样的。

我们期望的是同时匹配了title字段和body字段的文档能够拥有更高的排名,但是结果并非如此。需要记住:dis_max查询只是简单的使用最佳匹配查询子句得到的_score

tie_breaker

但是,将其它匹配的查询子句考虑进来也是可能的。通过指定tie_breaker参数:

{
"query": {
"dis_max": {
"queries": [
{ "match": { "title": "Quick pets" }},
{ "match": { "body": "Quick pets" }}
],
"tie_breaker": 0.3
}
}
}

它会返回以下结果:

{
"hits": [
{
"_id": "2",
"_score": 0.14757764,
"_source": {
"title": "Keeping pets healthy",
"body": "My quick brown fox eats rabbits on a regular basis."
}
},
{
"_id": "1",
"_score": 0.124275915,
"_source": {
"title": "Quick brown rabbits",
"body": "Brown rabbits are commonly seen."
}
}
]
}

现在文档2的分值比文档1稍高一些。

tie_breaker参数会让dis_max查询的行为更像是dis_maxbool的一种折中。它会通过下面的方式改变分值计算过程:

  1. 取得最佳匹配查询子句的_score
  2. 将其它每个匹配的子句的分值乘以tie_breaker
  3. 将以上得到的分值进行累加并规范化。

通过tie_breaker参数,所有匹配的子句都会起作用,只不过最佳匹配子句的作用更大。

NOTE

tie_breaker的取值范围是01之间的浮点数,取0时即为仅使用最佳匹配子句(译注:和不使用tie_breaker参数的dis_max查询效果相同),取1则会将所有匹配的子句一视同仁。它的确切值需要根据你的数据和查询进行调整,但是一个合理的值会靠近0,(比如,0.1 -0.4),来确保不会压倒dis_max查询具有的最佳匹配性质。

原文地址 https://blog.csdn.net/dm_vincent/article/details/41820537

[Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优(转)的更多相关文章

  1. [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优

    最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/1 { "title": " ...

  2. [Elasticsearch2.x] 多字段搜索 (二) - 最佳字段查询及其调优 <译>

    最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/ { "title": "Q ...

  3. Elasticsearch索引和查询性能调优的21条建议

    Elasticsearch部署建议 1. 选择合理的硬件配置:尽可能使用 SSD Elasticsearch 最大的瓶颈往往是磁盘读写性能,尤其是随机读取性能.使用SSD(PCI-E接口SSD卡/SA ...

  4. Elasticsearch 6.x版本全文检索学习之集群调优建议

    1.系统设置要到位,遵照官方建议设置所有的系统参数. https://www.elastic.co/guide/en/elasticsearch/reference/6.7/setup.html 部署 ...

  5. Elasticsearch 全字段搜索_all,query_string查询,不进行分词

    最近在使用ELasitcsearch的时候,需要用到关键字搜索,因为是全字段搜索,就需要使用_all字段的query_string进行搜索. 但是在使用的时候,遇到问题了.我们的业务并不需要分词,我在 ...

  6. [Elasticsearch] 多字段搜索 (五) - 以字段为中心的查询

    以字段为中心的查询(Field-centric Queries) 上述提到的三个问题都来源于most_fields是以字段为中心(Field-centric),而不是以词条为中心(Term-centr ...

  7. Hadoop作业性能指标及參数调优实例 (二)Hadoop作业性能调优7个建议

    作者:Shu, Alison Hadoop作业性能调优的两种场景: 一.用户观察到作业性能差,主动寻求帮助. (一)eBayEagle作业性能分析器 1. Hadoop作业性能异常指标 2. Hado ...

  8. scikit-learn网格搜索来进行高效的参数调优

    内容概要¶ 如何使用K折交叉验证来搜索最优调节参数 如何让搜索参数的流程更加高效 如何一次性的搜索多个调节参数 在进行真正的预测之前,如何对调节参数进行处理 如何削减该过程的计算代价 1. K折交叉验 ...

  9. MySQL架构优化实战系列2:主从复制同步与查询性能调优

随机推荐

  1. js中的throw err的作用

    1.阻止程序的运行 2.把错误消息打到控制台

  2. MySql Connector/c++8中JSON处理Demo

    #include <iostream> #include <vector> #include <mysqlx/xdevapi.h> using std::cout; ...

  3. 最大的最大公约数( 51nod-1179)

    妈耶有日期显示啊,我还写什么... 给出N个正整数,找出N个数两两之间最大公约数的最大值. 例如:N = 4,4个数为:9 15 25 16,两两之间最大公约数的最大值是15同25的最大公约数5.   ...

  4. docker安装MySQL 8.0及初始化错误处理

      Preface          Several days ago,I've implement a docker environmnet,I'm gonna Install a MySQL 8. ...

  5. python核心编程2 第十五章 练习

    15-1.识别下列字符串 :“bat ”.“bit ”.“but ”.“hat ”.“hit” 或 “hut ” import re from random import choice strtupl ...

  6. 大数据开发从入门小白到删库跑路(一)- 获取Hadoop

    Hadoop是一个可以通过相对简单编程模型实现跨多台计算机集群分布式处理大型数据集的框架.它不是依赖于高额成本的硬件可靠性来提供高可用性,Hadoop的设计能从单个服务器扩展到数千台机器,每个机器提供 ...

  7. jQuery的封装

    封装,最简单的效果就是一个效果你可以重复的去调用   本来前端之路时间不是很长,但是对封装还是有一点点自己个人的理解,曾经踩过的坑也不在少数,最后总结出我个人风格的封装,听一位大神指点过,每个人都有属 ...

  8. ubuntu系統如何啟動root用戶登陸?

    之前分享過關於這個問題的文章,現在自己在分享一個關於這個問題的文章給大家.為了學習Linux,一氣之下把win10的換成了ubuntu的系統.安裝就不給大家介紹了(網上很多教程). 在我們安裝好之後, ...

  9. PHP生成一个六位数的邀请码

    PHP生成一个六位数的邀请码 $unique_no = substr(base_convert(md5(uniqid(md5(microtime(true)),true)), 16, 10), 0, ...

  10. Angular : 响应式编程, 组件间通信, 表单

    Angular 响应式编程相关 ------------------------------------------------------------------------------------ ...