找出倒排表里两个关键字对应的doc交集
下面这段文字摘自http://blog.csdn.net/ToBeAndNotToBe/archive/2010/09/25/5904467.aspx
介绍了lucene里边倒排表n个关键字所对应的doc的交集。
可能大家都知道,lucene采用了传统搜索引擎中倒排表的数据结构.在搜索时,假设我们要查询"+(a:test)+(b:test1)"的话,首先要先查询得到a字段中包含 test关键字的倒排表,然后查询得到b字段中包含test1关键字的倒排表,然后对两个倒排表结构进行merge操作:计算两者间的交集就是我们的查询结果.
当然这只是其中一个例子罢了.实际情况中,因为查询条件不同和复杂性,我们可能会遇到更 多对倒排表的操作:交集,并集,差集等.本文主要讲述lucene如何对交集进行处理:合并倒排表,生成SumScorer结果.
第一步:过滤筛选:
先对每个倒排表进行检查:每个倒排表都是一个DocIdSetIterator,如果其中一个倒排表中list为空,则说明交集肯定为空,不需要进行接下来的工作:
for (int i = 0; i < scorers.length; i++) { if (scorers[i].nextDoc() == NO_MORE_DOCS) { // If even one of the sub-scorers does not have any documents, this // scorer should not attempt to do any more work. lastDoc = NO_MORE_DOCS; return; } }
Arrays.sort(scorers, new Comparator() { // sort the array public int compare(Object o1, Object o2) { return ((Scorer) o1).docID() - ((Scorer) o2).docID(); } });
if (doNext() == NO_MORE_DOCS) { // The scorers did not agree on any document. lastDoc = NO_MORE_DOCS; return; }/*doNext():该方法做的事情就是:比如倒排表数组中每个倒排表第一个docId分别为1,3,4,5,6,7;因为每个倒排表迭代器都是升序的,所以其实1,3,4,5,6在最后一个倒排表中没有,所以每个倒排表都应该从7开始,而不是1:*/ int first = 0; int doc = scorers[scorers.length - 1].docID(); Scorer firstScorer; while ((firstScorer = scorers[first]).docID() < doc) { doc = firstScorer.advance(doc); first = first == scorers.length - 1 ? 0 : first + 1; } return doc;/*advance方法: if (lastDoc == NO_MORE_DOCS) { return lastDoc; } else if (scorers[(scorers.length - 1)].docID() < target) { scorers[(scorers.length - 1)].advance(target); } return lastDoc = doNext();*/