本章翻译自Elasticsearch官方指南的Controlling Relevance一章。html
有时咱们不须要TF/IDF。咱们想知道的只是一个特定的单词是否出如今了字段中。好比咱们正在搜索度假酒店,但愿它拥有的卖点越多越好:json
而关于度假酒店的文档相似下面这样:缓存
{ "description": "A delightful four-bedroomed house with ... " }
可使用一个简单的match查询:elasticsearch
GET /_search
{
"query": { "match": { "description": "wifi garden pool" } } }
然而,咱们须要的并非真正的全文搜索。此时TF/IDF只会碍手碍脚。咱们不在乎wifi是不是一个常见的词条,也不在乎它在文档中出现的是否频繁。咱们在乎的只是它是否出现了。实际上,咱们只是想经过卖点来对这些度假酒店进行排序 - 越多越好。若是拥有一个卖点,那么它的分值就是1,若是没有它的分值就是0。ide
首先介绍constant_score查询。该查询可以包含一个查询或者一个过滤器,全部匹配文档的相关度分值都为1,不考虑TF/IDF:ui
GET /_search
{
"query": { "bool": { "should": [ { "constant_score": { "query": { "match": { "description": "wifi" }} }}, { "constant_score": { "query": { "match": { "description": "garden" }} }}, { "constant_score": { "query": { "match": { "description": "pool" }} }} ] } } }
大概并非全部的卖点都同等重要 - 其中的某些更有价值。若是最看中的卖点是泳池,那么咱们能够对它进行相应提高:spa
GET /_search
{
"query": { "bool": { "should": [ { "constant_score": { "query": { "match": { "description": "wifi" }} }}, { "constant_score": { "query": { "match": { "description": "garden" }} }}, { "constant_score": { "boost": 2 "query": { "match": { "description": "pool" }} }} ] } } }
NOTE翻译
每一个结果的最终分值并非将全部匹配子句的分值累加而获得。Coordination因子和查询归约因子(Query Normalization Factor)仍然会被考虑在内。orm
咱们能够在度假酒店的文档中添加一个not_analyzed类型的features字段:htm
{ "features": [ "wifi", "pool", "garden" ] }
默认状况下,一个not_analyzed字段的字段长度归约(Field-length Norm)是被禁用的,同时其index_options也会被设置为docs,从而禁用词条频度(Term Frequencies),可是问题仍是存在:每一个词条的倒排文档频度(Inverse Document Frequency)仍然会被考虑。
仍然使用constant_score查询:
GET /_search
{
"query": { "bool": { "should": [ { "constant_score": { "query": { "match": { "features": "wifi" }} }}, { "constant_score": { "query": { "match": { "features": "garden" }} }}, { "constant_score": { "boost": 2 "query": { "match": { "features": "pool" }} }} ] } } }
实际上,每一个卖点都应该被视为一个过滤器。度假酒店要么有该卖点,要么没有 - 使用过滤器彷佛是更天然的选择。而且若是咱们使用了过滤器,还能够得益于过滤器缓存这一功能。
不使用过滤器的根源在于:过滤器不会计算相关度分值。咱们须要的是一座用来链接过滤器和查询的桥梁。而function_score查询就可以作到这一点,而且它也提供了更多的功能。