注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

Lucene源代码分析[-7]  

2009-07-08 22:34:43|  分类: Lucene |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

         昨天太困太累,看源码我自己都糊涂了,今天好象精神稍好一点,把一些重要的地方再看一下:

public boolean next() throws IOException {

    if (firstTime) {

       init(true);

    } else if (more) {

       more = last().next(); // trigger further scanning

    }

    return doNext();

}

    如果是firstTime,就初始化:

private void init(boolean initScorers) throws IOException {

    //  compute coord factor

    coord = getSimilarity().coord(scorers.size(), scorers.size());

 

    more = scorers.size() > 0;

 

    if (initScorers) {

       // move each scorer to its first entry

       Iterator i = scorers.iterator();

       while (more && i.hasNext()) {

           more = ((Scorer) i.next()).next();

       }

       if (more)

           sortScorers(); // initial sort of list

    }

 

    firstTime = false;

}

    我们看到这里的coord在这里用的是DefaultSimilarity,它返回的总是1,而在while循环中,next调用的是TermScorer中的next,这个next我们以前已经见过:

public boolean next() throws IOException {

    pointer++;

    if (pointer >= pointerMax) {

       pointerMax = termDocs.read(docs, freqs); // refill buffer

       if (pointerMax != 0) {

           pointer = 0;

       } else {

           termDocs.close(); // close stream

           doc = Integer.MAX_VALUE; // set to sentinel value

           return false;

       }

    }

    doc = docs[pointer];

    return true;

}

    我们接着看如果我们所有的scorerhasNext(如果你对这有什么疑问,你就把BooleanQuery中的一个词改成在document中没有出现过的),那么我们就sortScorers

private void sortScorers() {

    // move scorers to an array

    Scorer[] array = (Scorer[]) scorers.toArray(new

Scorer[scorers.size()]);

    scorers.clear(); // empty the list

 

    // note that this comparator is not consistent with equals!

    Arrays.sort(array, new Comparator() { // sort the array

              public int compare(Object o1, Object o2) {

                  return ((Scorer) o1).doc() - ((Scorer) o2).doc();

              }

           });

 

    for (int i = 0; i < array.length; i++) {

       scorers.addLast(array[i]); // re-build list, now sorted

    }

}

    我们看到这里是用一个score中的doc序号来排序。再看一下doNext函数:

private boolean doNext() throws IOException {

    while (more && first().doc() < last().doc()) {

       more = first().skipTo(last().doc()); // skip first upto last

       scorers.addLast(scorers.removeFirst()); // move first to last

    }

    return more; // found a doc with all clauses

}

    在这次,因为我们已经排过序了,所以这里不会执行,直接返回more

/** Skips to the first match beyond the current whose document number is

 * greater than or equal to a given target.

*/

public boolean skipTo(int target) throws IOException {

    // first scan in cache

    for (pointer++; pointer < pointerMax; pointer++) {

       if (docs[pointer] >= target) {

           doc = docs[pointer];

           return true;

       }

    }

 

    // not found in cache, seek underlying stream

    boolean result = termDocs.skipTo(target);

    if (result) {

       pointerMax = 1;

       pointer = 0;

       docs[pointer] = doc = termDocs.doc();

       freqs[pointer] = termDocs.freq();

    } else {

       doc = Integer.MAX_VALUE;

    }

    return result;

}

    这个函数先在cache中找,如果找不到就在底层的stream中找,我们看到一个非常重要的函数skipTo

/** Optimized implementation. */

public boolean skipTo(int target) throws IOException {

    if (df >= skipInterval) { // optimized case

 

       if (skipStream == null)

           skipStream = (IndexInput) freqStream.clone(); // lazily clone

 

       if (!haveSkipped) { // lazily seek skip stream

           skipStream.seek(skipPointer);

           haveSkipped = true;

       }

 

       // scan skip data

       int lastSkipDoc = skipDoc;

       long lastFreqPointer = freqStream.getFilePointer();

       long lastProxPointer = -1;

       int numSkipped = -1 - (count % skipInterval);

 

       while (target > skipDoc) {

           lastSkipDoc = skipDoc;

           lastFreqPointer = freqPointer;

           lastProxPointer = proxPointer;

 

           if (skipDoc != 0 && skipDoc >= doc)

              numSkipped += skipInterval;

 

           if (skipCount >= numSkips)

              break;

 

           skipDoc += skipStream.readVInt();

           freqPointer += skipStream.readVInt();

           proxPointer += skipStream.readVInt();

 

           skipCount++;

       }

 

       // if we found something to skip, then skip it

       if (lastFreqPointer > freqStream.getFilePointer()) {

           freqStream.seek(lastFreqPointer);

           skipProx(lastProxPointer);

 

           doc = lastSkipDoc;

           count += numSkipped;

       }

 

    }

 

    // done skipping, now just scan

    do {

       if (!next())

           return false;

    } while (target > doc);

    return true;

}

    numSkipped并不是跳多少次,而是跳了多少次,要跳多少次在seek已经计算出来了,就是numSkips,我们看到我们在建索引时见过的skipStream中保存的三个值在这里读出来,也就是skip,当跳到numSkips次,我们开始读,next函数比较简单,也很面熟:

public boolean next() throws IOException {

    while (true) {

       if (count == df)

           return false;

 

       int docCode = freqStream.readVInt();

       doc += docCode >>> 1; // shift off low bit

       if ((docCode & 1) != 0) // if low bit is set

           freq = 1; // freq is one

       else

           freq = freqStream.readVInt(); // else read freq

 

       count++;

 

       if (deletedDocs == null || !deletedDocs.get(doc))

           break;

       skippingDoc();

    }

    return true;

}

    现在转回去看doNext,它的while循环开始是在first scorer里面找有没有大于last scorer中的第一个doc序号,因为最后的一个scorer的第一个doc序号是所以scorer第一个doc序号中最小的,但是这里是MUST,也就是合取,即如果要一个文档包含所有需要的词。而下一句是把第一个scorer换到最后一个,请注意,第一个scorer中的第一个doc序数已经不是以前的序数了,它在TermScorerdoc=docs[pointer]中已经改变。你也许会想,这样换来换去,岂不是结束不了循环,也不是的,如果大家开始都一样了,那么在第一个和最后一个Scorerdoc序号一样的时候,就结束了。

    那么在找下一个符合搜索条件的文档时,是用ConjunctionScorer中的next函数中的last().next来完成的。

 

 

 

 

  评论这张
 
阅读(1173)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017