文档评分
对于文档的评分而言 在Lucene当中就是给给定的查询文档赋予_score
的过程,Lucene默认的评分模型是词频/逆文档频率来进行评分。
Lucene的评分规则
当一个文档可以让Lucene索引,就是证明文档和检索条件是匹配,针对相关性Lucene就会对抓取的文档有一个评分,除了constant_score场景中返回的评分都是一样的,在其余场景中文档的评分不是一样的。因为每个文档的得分 和该文档的字段长度 索引是时候的映射权重,已经查询的时候查询权重,还有是不是很稀少的词组,或者是高频出现的短语;
Lucene的评分公式
这个公式描述的是一个查询和文档的对应关系的函数,
coord(q,d): 协调因子,它的计算是基于文档d中所包含的所有可供查询的词条数量
queryNorm: 在给出每个查询条目的方差和后,计算某查询的标准化值
求和公式 :代表词频和逆文档 * 查询权重 和索引权重 ;Lucene默认使用TF/IDF打分;这个规则的主要体现就是1 物以稀为贵,越罕见的词汇 得分越高,2 文档字段越短 文档得分越高,3 查询权重或者索引权重高的字段 文档评分更高
相似度评分模型
除了默认提供的TF/IDF打分规则 Lucene对外同样提供了多种相关性的算法用于切换,在es当中也可以直接配置;
- Okapi BM25评分模型
基于概率模型的一种相似度模型,用来估算文档和给定查询的概率,在es中配置使用similaryName=BM25
- 随机偏离模型
这个是基于同名概率的相似度模型,在es中配置使用similaryName=DFR
- 基于信息的模型
和随机模型类似,但是在自然语言处理上该模型具有较好的效果,在es中配置使用similaryName=IB
- LM Dirichlet模型
这个相似度模型结合狄利克雷先验和贝叶斯平滑,在es中配置使用similaryName=LMDirichlet
- LM Jelinek Mercer模型
这个相似度模型使用了Jelinek Mercer平滑方法,在es中配置使用similaryName=LMJelinekMercer
在ElasticSearch中我们可以针对整个索引使用打分模式,也可以对字段使用打分
ElasticSearch的打分
在Lucene打分规则的基础之上,ElasticSearch还提供了二次评分文档评分基础治丧二次评分来计算topN,可以使用function_score
和script_score
查询
先进行评分后过滤
GET /library/_search
{
"query":{
"term":{
"title":{
"value":"ElasticSearch"
}
}
},
"filter":{
"term":{
"copies":{
"value":"1"
}
}
}
}
这就是显然的 先查询后过滤,过滤不会对评分产生影响,过滤主要是为了用于缩小结果范围,可是检索不仅是会缩小结果的范围,还会控制文档评分,对文档的评分就意味着会使用更多的CPU对多个分片读取到的数据进行打分,也就是后置过滤;在term阶段是会对文档进行打分,由于我们要过滤得到doc2和doc4,对doc3的打分显得如此的苍白无力,还耗费cpu。
先过滤后进行评分
GET /library/_search
{
"query":{
"filtered":{
"query":{
"term":{
"title":{
"value":"ElasticSearch"
}
}
},
"filter":{
"term":{
"copies":{
"value":"1"
}
}
}
}
}
}
使用filtered
的是过滤查询 不是走的方式是先去根据过滤条件来控制 返回的多个分区的文档数目然后再去进行评分。
在常规的查询场景当中,使用过滤查询会比后置过滤的性能好很多,判断当场查询的数据的量级,如果说走过滤器开销小 而起容易使用缓存 直接使用过滤查询就OK,相反如果这些数据是不容易使用缓存的数据,而起每次查询是需要去进行CPU的计算,存在字段内部存在大量的唯一值。你就可以使用后置过滤。或者可以优化过滤查询的时间粒度。
过滤器缓存
ElasticSearch内部提供了多种缓存,过滤器缓存只是最简单的一种,ElasticSearch对过滤器缓存的结果 定义了针对索引级别和节点级别的缓存,默认是节点界别的,就是当使用filtered
查询之后,往后的查询速度提升会很明显。配置参数在elasticsearch.yml
文件中的配置项 index.cache.filter.type=node,还可以配置过滤器缓存的大小index.cache.filter.size=10(10%) ,默认是当前节点的最大堆内存的百分比来分配;既然是缓存就是有淘汰算法,过滤器缓存就是使用的LRU算法,最近使用最少的数据就会被淘汰;
常用的过滤器缓存的配置
- index.cache.filter.type
默认是 node 节点级别 备选有resident,不会被lru淘汰只有调用API才可以是删除。还有就是weak和soft;这俩个配置值,在JVM内存吃紧的情况会被释放,首先清除的是weak,然后是soft和JVM的垃圾回收不谋而合;
- index.cache.filter.max_size
默认是-1 无限制
- index.cache.filter.expire
默认是-1 永不过期,只会在lru策略淘汰。如果设置了过期时间,会在最后一次访问之后 达到你配置的过期时间,之后淘汰;