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

Koala++'s blog

计算广告学 RTB

 
 
 

日志

 
 

Lucene源代码分析[-2]  

2009-07-07 11:10:43|  分类: Lucene |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

    开始一个有意义的例子:

public static void main( String[] args ) throws Exception

{

    IndexSearcher searcher = new IndexSearcher( "E:\\a" );

    Term t = new Term( "TheField", "hello" );

    Query q = new TermQuery( t );

   

    searcher.search( q );

   

    searcher.close();

}

    我把TermTermQuery列出来,来证明它有多么不值得列出来:

Term(String fld, String txt, boolean intern) {

    field = intern ? fld.intern() : fld; // field names are interned

    text = txt; // unless already known to be

}

public TermQuery(Term t) {

    term = t;

}

    我们看search函数:

public final Hits search(Query query) throws IOException {

    return search(query, (Filter) null);

}

    Filter这个我们以后再看,接着跟进:

public Hits search(Query query, Filter filter) throws IOException {

    return new Hits(this, query, filter);

}

    还要接着看Hits的构造函数:

Hits(Searcher s, Query q, Filter f) throws IOException {

    weight = q.weight(s);

    searcher = s;

    filter = f;

    getMoreDocs(50); // retrieve 100 initially

}

    看一下Query中的weight函数:

public Weight weight(Searcher searcher) throws IOException {

    Query query = searcher.rewrite(this);

    Weight weight = query.createWeight(searcher);

    float sum = weight.sumOfSquaredWeights();

    float norm = getSimilarity(searcher).queryNorm(sum);

    weight.normalize(norm);

    return weight;

}

    还没有到头,甚至还没有一点到头的迹象,接着列吧:

public Query rewrite(Query original) throws IOException {

    Query query = original;

    for (Query rewrittenQuery = query.rewrite(reader);

rewrittenQuery != query;

rewrittenQuery = query.rewrite(reader)) {

        query = rewrittenQuery;

    }

    return query;

}

    我们看一下这里的query.rewrite函数:

/** Expert: called to re-write queries into primitive queries. For example,

 * a PrefixQuery will be rewritten into a BooleanQuery that consists

 * of TermQuerys. */

public Query rewrite(IndexReader reader) throws IOException {

    return this;

}

    看上面的注释,是把一个query写成primitive queries,举一个例子一个PrefixQuery将写成一个BooleanQuery,其中由TermQuerys组成。我们这里就是TermQuery,不用再重写,直接返回。

         回到weight函数,我们看下一个函数createWeight

protected Weight createWeight(Searcher searcher) throws IOException {

    return new TermWeight(searcher);

}

         跟进去:

public TermWeight(Searcher searcher) throws IOException {

    this.similarity = getSimilarity(searcher);

    idf = similarity.idf(term, searcher); // compute idf

}

         我们终于看到一个让我们激动的变量了idf

/** Expert: Returns the Similarity implementation to be used for

 * this query. Subclasses may override this method to specify

 * their own Similarity implementation, perhaps one that delegates

 * through that of the Searcher. By default the Searcher's Similarity

 * implementation is returned.*/

public Similarity getSimilarity(Searcher searcher) {

    return searcher.getSimilarity();

}

         注意注释里的一个词delegate,可见它的重要性。

public Similarity getSimilarity() {

    return this.similarity;

}

         我们看到similarity只是简单地被返回了。接着看similarity.idf

public float idf(Term term, Searcher searcher) throws IOException {

    return idf(searcher.docFreq(term), searcher.maxDoc());

}

         我们再看searcher.docFreq这个函数:

public int docFreq(Term term) throws IOException {

    return reader.docFreq(term);

}

         我们已经看到了曙光:

public int docFreq(Term t) throws IOException {

    TermInfo ti = tis.get(t);

    if (ti != null)

       return ti.docFreq;

    else

       return 0;

}

         我们看到tis.get函数:

TermInfo get(Term term) throws IOException {

    if (size == 0)

       return null;

 

    ensureIndexIsRead();

 

    SegmentTermEnum enumerator = getEnum();

    if (enumerator.term() != null // term is at or past current

           && ((enumerator.prev() != null

&& term.compareTo(enumerator.prev()) > 0)

|| term.compareTo(enumerator.term()) >= 0)) {

       int enumOffset = (int) (enumerator.position /

enumerator.indexInterval) + 1;

       if (indexTerms.length == enumOffset // but before end of block

              || term.compareTo(indexTerms[enumOffset]) < 0)

           return scanEnum(term); // no need to seek

    }

 

    // random-access: must seek

    seekEnum(getIndexOffset(term));

    return scanEnum(term);

}

         我们看到这里感觉有点后悔,为什么当时不看完呢?但是我们当时看过另一个get函数,并且与这个函数很相似,中间的那个if第一句表示的是position就在最后,而第二句用termindexTerms里面的term比较看在不在那范围中,我们这里看一下getIndexOffset函数,seekEnumscanEnum讲过了,就不看了:

private final int getIndexOffset(Term term) {

    int lo = 0; // binary search indexTerms[]

    int hi = indexTerms.length - 1;

 

    while (hi >= lo) {

       int mid = (lo + hi) >> 1;

       int delta = term.compareTo(indexTerms[mid]);

       if (delta < 0)

           hi = mid - 1;

       else if (delta > 0)

           lo = mid + 1;

       else

           return mid;

    }

    return hi;

}

         折半查找,或说说是二分查找,讲一个很经典的事,看起来很简单,很短的代码。折半查找在1946年提出,但是第一个正确的二分查找程序出现在1962年。

         简单地说一下,我们看到getTerm最后返回的是TermInfo,下面是TermInfo中的成员:

final class TermInfo {

  /** The number of documents which contain the term. */

  int docFreq = 0;

 

  long freqPointer = 0;

  long proxPointer = 0;

  int skipOffset;

}

         回到docFreq函数中,我们看到,它返回的是TermInfo中的docFreq,我将在新的一篇中介绍idf函数。

 

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

历史上的今天

评论

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

页脚

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