[Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优(转)
最佳字段(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
查询是如何计算得到其分值的:
- 运行
should
子句中的两个查询 - 相加查询返回的分值
- 将相加得到的分值乘以匹配的查询子句的数量
- 除以总的查询子句的数量
文档1在两个字段中都包含了brown
,因此两个match
查询都匹配成功并拥有了一个分值。文档2在body
字段中包含了brown
以及fox
,但是在title
字段中没有出现任何搜索的单词。因此对body
字段查询得到的高分加上对title
字段查询得到的零分,然后在乘以匹配的查询子句数量1,最后除以总的查询子句数量2,导致整体分值比文档1的低。
在这个例子中,title
和body
字段是互相竞争的。我们想要找到一个最佳匹配(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_max
和bool
的一种折中。它会通过下面的方式改变分值计算过程:
- 取得最佳匹配查询子句的
_score
。 - 将其它每个匹配的子句的分值乘以
tie_breaker
。 - 将以上得到的分值进行累加并规范化。
通过tie_breaker
参数,所有匹配的子句都会起作用,只不过最佳匹配子句的作用更大。
NOTE
tie_breaker
的取值范围是0
到1
之间的浮点数,取0
时即为仅使用最佳匹配子句(译注:和不使用tie_breaker
参数的dis_max
查询效果相同),取1
则会将所有匹配的子句一视同仁。它的确切值需要根据你的数据和查询进行调整,但是一个合理的值会靠近0
,(比如,0.1
-0.4
),来确保不会压倒dis_max
查询具有的最佳匹配性质。原文地址 https://blog.csdn.net/dm_vincent/article/details/41820537
[Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优(转)的更多相关文章
- [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优
最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/1 { "title": " ...
- [Elasticsearch2.x] 多字段搜索 (二) - 最佳字段查询及其调优 <译>
最佳字段(Best Fields) 假设我们有一个让用户搜索博客文章的网站,就像这两份文档一样: PUT /my_index/my_type/ { "title": "Q ...
- Elasticsearch索引和查询性能调优的21条建议
Elasticsearch部署建议 1. 选择合理的硬件配置:尽可能使用 SSD Elasticsearch 最大的瓶颈往往是磁盘读写性能,尤其是随机读取性能.使用SSD(PCI-E接口SSD卡/SA ...
- Elasticsearch 6.x版本全文检索学习之集群调优建议
1.系统设置要到位,遵照官方建议设置所有的系统参数. https://www.elastic.co/guide/en/elasticsearch/reference/6.7/setup.html 部署 ...
- Elasticsearch 全字段搜索_all,query_string查询,不进行分词
最近在使用ELasitcsearch的时候,需要用到关键字搜索,因为是全字段搜索,就需要使用_all字段的query_string进行搜索. 但是在使用的时候,遇到问题了.我们的业务并不需要分词,我在 ...
- [Elasticsearch] 多字段搜索 (五) - 以字段为中心的查询
以字段为中心的查询(Field-centric Queries) 上述提到的三个问题都来源于most_fields是以字段为中心(Field-centric),而不是以词条为中心(Term-centr ...
- Hadoop作业性能指标及參数调优实例 (二)Hadoop作业性能调优7个建议
作者:Shu, Alison Hadoop作业性能调优的两种场景: 一.用户观察到作业性能差,主动寻求帮助. (一)eBayEagle作业性能分析器 1. Hadoop作业性能异常指标 2. Hado ...
- scikit-learn网格搜索来进行高效的参数调优
内容概要¶ 如何使用K折交叉验证来搜索最优调节参数 如何让搜索参数的流程更加高效 如何一次性的搜索多个调节参数 在进行真正的预测之前,如何对调节参数进行处理 如何削减该过程的计算代价 1. K折交叉验 ...
- MySQL架构优化实战系列2:主从复制同步与查询性能调优
随机推荐
- jquery mobile 移动web(4)
下拉菜单: 设置label 元素的for 属性为 select label 元素的文本内容作为选项的名称 定义div元素并设置data-role 属性值为 fieldcontain. <div ...
- ionic 安装步骤
安装ionic和cordova 1,需要首先安装好nodejs,然后通过npm来安装 npm install -g cordova ionic 注意:可能遇到的错误:Error: Cannot fi ...
- plupload批量上传分片(后台代码)
plupload批量上传分片功能, 对于文件比较大的情况下,plupload支持分片上传,后台代码如下: /** * * 方法:upLoadSpecialProgramPictrue * 方法说明:本 ...
- web常用软件
编辑器: VSCode HBuilder WebStorm NotePad++ Eclipse Atom 常用插件: SwitchyOmega Vue-Tools server类: tomcat Ng ...
- Codeforces Round #491 (Div. 2)部分题解
这场比赛好鬼畜啊,,A题写崩了wa了4遍,心态直接爆炸,本来想弃疗了,结果发现BCD都是傻逼题.. A. If at first you don't succeed...(容斥原理) 题目大意: 有$ ...
- cors(Cross-origin resource sharing)跨域资源共享
阮一峰老师的文章(http://www.ruanyifeng.com/blog/2016/04/cors.html)跨域资源共享详解和https://developer.mozilla.org/zh- ...
- I/O流、字符集
1)InputStream.OutPutStream是输出输入的基础流,均为抽象类,提供了read和writer方法,所有的子类均实现read和writer方法,read在遇到输入源的结尾时返回-1. ...
- python+matplotlib 绘制等高线
python+matplotlib 绘制等高线 步骤有七: 有一个m*n维的矩阵(data),其元素的值代表高度 构造两个向量:x(1*n)和y(1*m).这两个向量用来构造网格坐标矩阵(网格坐标矩阵 ...
- centos安装zabbix(server+agent)
本文包含zabbix_server编译安装,zabbix_agent编译安装,中文字体修正 Mysql模板监控,Nginx模板监控,以及简单的web页面的使用 中文乱码的解决方案 zabbix乱码是字 ...
- python中如何统计一个类的实例化对象
类中的静态变量 需要通过类名.静态变量名 来修改 :通过对象不能修改 python中如何统计一个类的实例化对象?? class Person: #静态变量count,用于记录类被实例化的次数 coun ...