作者:刘晓国
在我们实际的查询中,我们总希望能把满足我们查询的结果排在查询的前面。在在 Elasticsearch 中,通过相关性的调整可以完成这个目的。在返回的结果中,得分最高的结果总排在第一名,依次类推,得分最低的排在最后。我们可以参考文章 “Elasticsearch:使用布尔查询提高搜索的相关性” 如何使用 bool 查询来提高一些文档的相关性。当然,我们也可以通过 “Elasticsearch:使用 function_score 及 soft_score 定制搜索结果的分数” 来通过 script 的方法来调整查询结果的分数。
在今天的文章中,我将介绍另外一种方法 boosting query。它也是来调整查询结果的分数来达到查询结果的排序。只是它可以针对不喜欢的文档进行减分从而达到 boost 其它匹配的文档。下面我来介绍一种这种方法。
首先 我们在 Kibana 中,我们导入如下的两个文档:
POST test/_bulk { "index" : { "_id" : "1" } } { "title" : "Elastic Stack", "content": "Logstash" } { "index" : { "_id" : "2" } } { "title" : "Elastic Stack", "content": "Beats" } { "index" : { "_id" : "3" } } { "title" : "Elastic Stack", "content": "Beats Test" }
我们做一个如下的查询:
GET test/_search { "query": { "match": { "title": "Elastic Stack" } } }
上面的查询结果显示为:
{ "took" : 4, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 3, "relation" : "eq" }, "max_score" : 0.26706278, "hits" : [ { "_index" : "test", "_type" : "_doc", "_id" : "1", "_score" : 0.26706278, "_source" : { "title" : "Elastic Stack", "content" : "Logstash" } }, { "_index" : "test", "_type" : "_doc", "_id" : "2", "_score" : 0.26706278, "_source" : { "title" : "Elastic Stack", "content" : "Beats" } }, { "_index" : "test", "_type" : "_doc", "_id" : "3", "_score" : 0.26706278, "_source" : { "title" : "Elastic Stack", "content" : "Beats Test" } } ] } }
从上面的显示结果我们可以看出来它们的分数都为:0.26706278,这是因为它们的 title 都是一样的 Elastic Stack。
现在的问题是我们更想查看内容是 Beats 的文档,而不是Logstash 的文档。也就是说,我们不想要看到有关 Logstash 的文档。针对这种要求,我们可以这么做:
GET test/_search { "query": { "boosting": { "positive": { "match": { "title": "Elastic Stack" } }, "negative": { "match": { "content": "Logstash" } }, "negative_boost": 0.5 } } }
在上面,我们针对 content 字段含有 Logstash 的文档对它加权 0.5,也就是对它进行减分。
经过上面的处理,我们查询的结果为:
{ "took" : 7, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 3, "relation" : "eq" }, "max_score" : 0.26706278, "hits" : [ { "_index" : "test", "_type" : "_doc", "_id" : "2", "_score" : 0.26706278, "_source" : { "title" : "Elastic Stack", "content" : "Beats" } }, { "_index" : "test", "_type" : "_doc", "_id" : "3", "_score" : 0.26706278, "_source" : { "title" : "Elastic Stack", "content" : "Beats Test" } }, { "_index" : "test", "_type" : "_doc", "_id" : "1", "_score" : 0.13353139, "_source" : { "title" : "Elastic Stack", "content" : "Logstash" } } ] } }
}
显然,content 字段含有 Logstash 的文档的分数明显比含有 Beats 的文档的分数少一半的分数。这样它的返回的结果排在最后。