在搜索阶段,每当Lucene找到一个满足查询条件的文档(Document),便会将该文档的文档号(docId)交给Collector,并在Collector中对收集的文档号集合进行排序(sorting)、过滤(filtering)或者用户自定义的操作。
本篇文章将根据图1中的类图(Class diagram),介绍Lucene常用的几个收集器(Collector):
图1:
下图中描述的是Collector处理文档的流程:
图2:
图3:
当索引目录中存在多个段时,我们需要从每个段中分别找出满足查询条件的文档,LeafReaderContext即用来描述某一个段的信息,并且通过它能获得一个LeafCollector对象,在本篇文章中我们只要知道LeafReaderContext有这个功能(functionality)即可,在后面介绍IndexReader的文章中会展开。
在搜索阶段,通过Collector类的方法来获得LeafCollector对象,下面是Collector类的代码,由于Collector类是一个接口类,并且只有两个接口方法,故列出并介绍:
xxxxxxxxxx
public interface Collector {
LeafCollector getLeafCollector(LeafReaderContext context) throws IOException;
boolean needsScores();
}
通过该方法获得一个LeafCollector对象,Lucene每处理完一个段,就会调用该方法获得下一个段对应的LeafCollector对象。
LeafCollector对象有什么作用:
xxxxxxxxxx
public interface LeafCollector {
void setScorer(Scorer scorer) throws IOException;
/** 参数doc即文档号docId*/
void collect(int doc) throws IOException;
}
设置该方法用来告知Lucene在搜索阶段,当找到一篇文档时,是否对其进行打分。如果用户期望的查询结果不依赖打分,那么可以设置为false来提高查询性能。
图4:
当Lucene找到一篇满足查询条件的文档,会调用LeafCollector的setScorer(Scorer score)方法来执行获得文档打分
的流程,随后在获得文档号docId
流程后获得一个docId,最后调用LeafCollector的collect(int doc)方法(参数doc即文档号docId)来实执行处理该文档
的流程,在该流程中,实现对文档进行排序(sorting)、过滤(filtering)或者用户自定义的操作。
在介绍完Collector处理文档的流程后,我们依次介绍图1中的收集器。
TimeLimitingCollector封装了其他的Collector,用来限制Collector处理文档的时间,即设定了一次查询允许的最长时间timeLimit。如果查询的时间超过timeLimit,那么会抛出超时异常TimeExceededException。
在哪些流程点会判断查询超时:
是否还有
LeafReaderContext
的流程点处理该文档
的流程点如何实现超时机制:
通过后台线程、解析值resolution、计数器counter实现、timeLimit
后台线程先执行counter的累加操作,即调用counter.addAndGet(resolution)的方法,随后调用Thread.sleep(resolution)的方法,如此反复。收集文档号的线程在 判断查询超时的流程点处通过counter.get()的值判断是否大于timeLimit
使用这种超时机制有什么注意点:
在开启贪婪模式的情况下(默认不开启),如果在LeafCollector.collect( )中判断出查询超时,那么还是会收集当前的文档号并随后抛出超时异常,注意的是如果在Collector.getLeafCollector( )中判断出查询超时,那么直接抛出超时异常。
剩余的Collector展开介绍会造成本篇文章篇幅过长,将在下一篇文章中展开。
点击下载附件