BooleanQuery的分析

       对于一次检索,检索的结果应该和查询相关,同时也应该和索引相关,所以lucene中常用

                                                  searcher.search(query)

来完成查询功能,searcher考虑了索引,query则考虑了查询的特点。

       lucene提供一个Query的抽象类来定义查询。由于查询是和具体的使用环境相关的,所以具有新特点的Query类型可能会不断的添加到系统中,这部分的设计应该较多的考虑扩展的需要。lucene-2.2支持的Query类型总共有下面10种

  • TermQuery
  • MultiTermQuery
  • BooleanQuery
  • WildcardQuery
  • PhraseQuery
  • PrefixQuery
  • MultiPhraseQuery
  • FuzzyQuery
  • RangeQuery
  • org.apache.lucene.search.spans.SpanQuery

         前面通过对search部分的源代码分析可以看出,最终searcher.search(Query)委托给Hits进行处理,Hits类中的处理如下

  Hits(Searcher s, Query q, Filter f) throws IOException {
    weight = q.weight(s);
    searcher = s;
    filter = f;
    getMoreDocs(50); // retrieve 100 initially
  }

           这里  ,q.weight(s)会返回一个Weight对象。

           gerMoreDocs(int)中又调用searcher的抽象方法search(),我们以Searcher的一个子类IndexSearcher为例,看一下search()主要完成的工作

  public void search(Weight weight, Filter filter,
                     final HitCollector results) throws IOException{
    HitCollector collector = results;
    if (filter != null) {
      final BitSet bits = filter.bits(reader);
      collector = new HitCollector() {
          public final void collect(int doc, float score) {
            if (bits.get(doc)) {                  // skip docs not in bits
              results.collect(doc, score);
            }
          }
        };
    }

    Scorer scorer = weight.scorer(reader);
    if (scorer == null)
      return;
    scorer.score(collector);
  }

          该方法体内,会使用Weight参数返回一个Scorer(打分器),而Scorer.score()会对结果打分,决定最终的查询结果。

          显然即使是Searcher的一个具体的子类IndexSearcher,它的search方法针对Query也是完全面向接口,它内部只定义了程序逻辑,具体的使用什么样的Query,什么样的Weight,什么样的Scorer,完全与Searcher无关,这样保证了Searcher类的独立性。

         Query定义了weight()的行为, 这里

 public Weight weight(Searcher searcher)
    throws IOException {
    Query query = searcher.rewrite(this);//对本Query对象进行预处理,转换为容易进行操作的Query
    Weight weight = query.createWeight(searcher);//具体的Query对象根据不同情况返回一个具体的Weight对象
    float sum = weight.sumOfSquaredWeights();
    float norm = getSimilarity(searcher).queryNorm(sum);
    weight.normalize(norm);
    return weight;
  }

       下面以BooleanQuery为例,说明search()方法中的

                Scorer scorer = weight.scorer(reader);

                 scorer.score(collector);

        的执行原理。

         下面的UML图简单的说明了具体的Query,Score和Weight类之间的关系

         BooleanQuery.createWeight()返回BooleanWeight对象,BooleanWeight的weights成员包含了BooleanQuery经过rewrite()之后的子Query的Weight值。

          BooleanWeight.scorer()方法实际返回的是一个BooleanScore2的对象,该对象将

BooleanWeight.weights中的每一个weight返回的Scorer分为三类,分别添加到三个ArrayList类型对象

prohibitedScorers,requiredScorers和optionalScorers中去。

          BooleanScorer2.score()方法实际完成两个工作:

         1 使用一个BooleanScorer对象,将前面的prohibitedScorers,requiredScorers和optionalScorers添加到BooleanScorer对象的subScore的成员中,该成员是一个SubScore类型的对象,属于链表结构,提供next()来获得所有的Scorer。

         2 调用BooleanScorer.score()。所有SubScorer依次处理和该Scorer相关的文档,完成内容的收集。

         SubScorer包括一个Scorer对象,并提供了一些精心设计的字段。

         整个的BooleanScorer.score()方法实际是通过一系列的SubScorer.score()完成,比较类似于管道的作用。一个大的执行是通过一系列相关的小管道的完成来实现的。

        这部分的设计思想很好的贯彻了抽象的概念,将查询的相关因素划分到两个部分,其中一个部分对另一个部分的使用以面向接口进行程序编写,如果处理的次数比较多的话,引入管道,链表的设计,可以确保任意次数的处理。

 

 

    

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值