本节书摘来华章计算机《深入理解Elasticsearch(原书第2版)》一书中的第2章 ,第2.4.2节,[美]拉斐尔·酷奇(Rafal Ku) 马雷克·罗戈任斯基(Marek Rogoziski)著 张世武 余洪淼 商旦 

2.4.2 过滤器的工作原理

前一小节我们已经提到,过滤不影响所匹配文档的得分。基于两个原因,这一点非常重要。第1个原因是性能。针对索引中的一组文档进行过滤操作是非常简单高效的。过滤器持有的关于文档的唯一重要信息是该文档是否匹配这个过滤器—仅仅一个标记而已。

过滤器通过返回一个被称为DocIdSet(org.apache.lucene.search.DocIdSet)的数据结构来提供这类匹配信息。这个数据结构的用途是为索引段提供经过滤器过滤后的数据。它可以使用Bits接口(org.apache.lucene.util.Bits)的有关实现。Bits接口可以随机访问过滤器中的文档信息(主要是检查索引段中的某个文档是否和该过滤器匹配)。Bits的数据结构非常高效,因为CPU可以使用位运算来完成过滤(有一个精巧的CPU部件用来处理这类运算,详情参考环形移位的维基百科http://en.wikipedia.org/wiki/Circular_shift)。DocIdSet还针对内部文档标识的有序集合提供了一个DocIdSetIterator迭代器给我们使用。

下表展示了这些类是如何使用Bits进行工作的。


es过滤词 elasticsearch 过滤器_es过滤词

Lucene(以及Elasticsearch)提供了DocIdSet的多种实现来应对不同场景。不同实现的性能各不相同。不过,选择合适的实现是Lucene和Elasticsearch的职责,我们一般不需要关心这一点,除非我们要针对它们进行功能扩展。
 不是所有的过滤器都使用Bits结构,比如数值区间过滤器、脚本过滤器、以及基于地理位置的一组过滤器。这些特殊的过滤器选择把数据记录在字段缓存里,然后再遍历所需处理的文档集合,逐个进行过滤操作。这意味着过滤器链条中的下一个过滤器只能获取到匹配前一个过滤器的文档集合。因此,可以针对这些过滤器进行优化,比如把最重的(译者注:匹配文档最多的,或者性能最差的)过滤器放到过滤器链的最后去执行。
布尔过滤器和与或非过滤器
我们在《Elasticsearch Server,Second Edition》一书中探讨了过滤器的有关知识,在这里只需要提醒读者注意一点:与或非过滤器不使用Bits,而布尔过滤器使用了Bits。因此,请尽可能使用布尔过滤器。与或非过滤器一般在需要脚本过滤、地理位置过滤和数值区间过滤时使用。还需要注意的是,如果把任何不使用Bits的过滤器嵌套在与或非过滤器中,它们同样不会用到Bits。
一般来讲,在组合使用多个处理器时,如果其中包含不使用Bits的处理器,则需要使用与或非处理器来对它们进行组合。而如果要组合的所有处理器都使用Bits,则可以选择使用布尔过滤器来组合它们。