原文链接:http://blog.csdn.net/dm_vincent/article/details/41820537
最佳字段(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
查询具有的最佳匹配性质。
(function() {
var s = “_” + Math.random().toString(36).slice(2);
document.write(‘ ‘);
(window.slotbydup=window.slotbydup || []).push({
id: ‘4774193’,
container: s,
size: ‘728,90’,
display: ‘inlay-fix’
});
})();
<div id="share_weibo">分享到:
<a data-type="sina" href="javascript:;" title="分享到新浪微博"><img src="/images/sina.jpg"></a>
<a data-type="qq" href="javascript:;" title="分享到腾讯微博"><img src="/images/tec.jpg"></a>
</div>
- 2016-04-21 07:43
- 浏览 2668
- 评论(0)
<li>分类:<a href="http://www.iteye.com/blogs/category/language">编程语言</a></li>
<li class="last"><a href="http://www.iteye.com/wiki/blog/2292755" target="_blank" class="more">查看更多</a></li>
</ul>
相关资源推荐
- elasticsearch笔记_多字段搜索(六)
- [Elasticsearch] 多字段搜索 (二) - 最佳字段查询及其调优
- ElasticSearch 2 (15) - 深入搜索系列之多字段搜索
- elasticsearch多字段搜索
- Elasticsearch 权威教程 - 多字段搜索
- [Elasticsearch] 多字段搜索 (六) - 自定义_all字段,跨域查询及精确值字段
- [Elasticsearch] 多字段搜索 (一) - 多个及单个查询字符串
- ElasticSearch多个字段分词查询高亮显示
- [Elasticsearch] 多字段搜索 (五) - 以字段为中心的查询
- [Elasticsearch] 多字段搜索 (三) - multi_match查询和多数字段
- elasticsearch查询多字段聚合
- 多字段搜索 (二) - 最佳字段查询及其调优
- ElasticSearch 5.X 搜索并用高亮显示
- elasticsearch索引(多字段类型字段—字段可检索可聚合)
- ElasticSearch Group by Multi Field,多字段聚合
- elasticsearch 多词短语位置匹配查询
- Elasticsearch 多字段查询
- elasticsearch系列-ES对多个字段聚合,select A,B,COUNT(*) from table group by A,B
- Elasticsearch Java API 实现搜索功能(2) 多字段匹配
- elasticsearch-基于多字段,字符串内部排序
评论