重新Query对象树及里边用到的常用算法

重建Query对象是个递归的过程,是个广度遍历树的过程。

BooleanQuery.reWrite()函数:

BooleanQuery clone = null;                    // recursively rewrite
    for (int i = 0 ; i < clauses.size(); i++) {
      BooleanClause c = clauses.get(i);
      Query query = c.getQuery().rewrite(reader);//重写
      if (query != c.getQuery()) {   // clause rewrote: must clone/分支重写过了,那么必须克隆一份
        if (clone == null)
          clone = (BooleanQuery)this.clone();
        clone.clauses.set(i, new BooleanClause(query, c.getOccur()));
      }
    }
    if (clone != null) {
      return clone;                               // some clauses rewrote
    } else
      return this;                                // no clauses rewrote
 

 为什么要重写Query呢?

 

 因为lucene不能直接处理MultiTermQuery,比如PrefixQuery、FuzzyQuery, TermQuery的重写直接返回其本身。

 

 对MultiTermQuery可以有两种处理方法:

 

   方法一,将多个term组成一个term,将包含他们的文档号取出来放到一起,作为一个倒排表来参与倒排表的合并。

 

   方法二,将多个term每个搞成一个TermQuery,它们一起组成一个BooleanQuery,他们之间是OR关系。

 

  1、 ConstantScoreQuery采用的是第一种方法,其构造

 

   new ConstantScoreQuery(new MultiTermQueryWrapperFilter<MultiTermQuery>(query))

 

  其中MultiTermQueryWrapperFilter的函数getDocIdSet() 是用于将多个term的倒排表进行合并的。

 

  其函数的主体如下:

 

 

 final FixedBitSet bitSet = new FixedBitSet(reader.maxDoc());//标志位的一个bitSet
      final int[] docs = new int[32];//用于取docId和freqs的缓冲
      final int[] freqs = new int[32];//用于取docId和freqs的缓冲
      TermDocs termDocs = reader.termDocs();//得到倒排表的读取器
      try {
        int termCount = 0;
        do {
          Term term = enumerator.term();
          if (term == null)
            break;
          termCount++;
          termDocs.seek(term);//得到该term的倒排表
          while (true) {
            final int count = termDocs.read(docs, freqs);//从倒排表中读取出文档号和词频
            if (count != 0) {
              for(int i=0;i<count;i++) {
                bitSet.set(docs[i]);//对该文档号在bieSet上对应的位置设置为1
              }
            } else {
              break;
            }
          }
        } while (enumerator.next());
 

 

    这样的算法使用在lucene中很多地方都用到了,一是使用缓存,二是使用bit标志位

 

   2、ScoringBooleanQueryRewrite以及子类ConstantScoreBooleanQueryRewrite采用方法二

 

   其rewrite函数主体:

 

 

  do {
          Term t = enumerator.term();
          if (t != null) {
            TermQuery tq = new TermQuery(t); // found a match
            tq.setBoost(query.getBoost() * enumerator.difference()); // set the boost
            result.add(tq, BooleanClause.Occur.SHOULD); // add to query
            count++;
          }
        } while (enumerator.next());  
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值