您的位置:首页 > 产品设计 > UI/UE

Lucene范围查询RangeQuery

2012-02-26 14:35 183 查看
 
关于范围查询RangeQuery。

RangeQuery是由两个词条作为上界和下界进行查询,同时指定了一个Boolean型参数,表示是否包括边界,这可以从

RangeQuery的构造方法看到:

    public RangeQuery(Term lowerTerm, Term upperTerm, boolean inclusive)

    {

        if (lowerTerm == null && upperTerm == null)

        {

            throw new IllegalArgumentException("At least one term must be non-null");

        }

        if (lowerTerm != null && upperTerm != null && lowerTerm.field() != upperTerm.field())

        {

            throw new IllegalArgumentException("Both terms must be for the same field");

        }

        // if we have a lowerTerm, start there. otherwise, start at beginning

        if (lowerTerm != null) {

            this.lowerTerm = lowerTerm;

        }

        else {

            this.lowerTerm = new Term(upperTerm.field(), "");

        }

        this.upperTerm = upperTerm;

        this.inclusive = inclusive;

    }

在构造一个RangeQuery的时候,不能使Term lowerTerm和Term upperTerm都为null,因为这样构造没有意义的。使用RangeQuery对于时间、数字序号等类似特征的词条具有很好的效果,但是作为普通词条意义不大,它会按照字母序来确定搜索范围。

可以指定Term lowerTerm和Term upperTerm中的一个为null,如果指定了Term upperTerm为null,会以Term lowerTerm为上界(即>=),同理,如果Term lowerTerm为null,会以Term upperTerm作为下界(即<=)。

依然使用文章
Lucene-2.2.0 源代码阅读学习(32) 使用的索引文件,建立测试文件,代码如下所示:

package org.apache.lucene.shirdrn.main;

import java.io.IOException;

import java.util.Date;

import java.util.List;

import org.apache.lucene.document.Document;

import org.apache.lucene.document.Field;

import org.apache.lucene.index.CorruptIndexException;

import org.apache.lucene.index.Term;

import org.apache.lucene.search.Hits;

import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.RangeQuery;

import org.apache.lucene.search.spans.SpanNearQuery;

import org.apache.lucene.search.spans.SpanQuery;

public class RangeQuerySearcher {

public static void main(String[] args) {

   String indexPath = "E:\\Lucene\\index";

   try {

    IndexSearcher searcher = new IndexSearcher(indexPath);

    String keywordA = "这些";

    Term termA = new Term("contents",keywordA);

   

    String keywordB = "辩论";

    Term termB = new Term("contents",keywordB);

   

   RangeQuery rangeQuery = new RangeQuery(termA,termA,true);

   

    Date startTime = new Date();

    Hits hits = searcher.search(rangeQuery);

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

     System.out.println("Document的内部编号为 : "+hits.id(i));

     Document doc = hits.doc(i);

     System.out.println("Document的得分为 : "+hits.score(i));

     List fieldList = doc.getFields();

     System.out.println("Document(编号) "+hits.id(i)+" 的Field的信息: ");

     for(int j=0;j<fieldList.size();j++){

      Field field = (Field)fieldList.get(j);

      System.out.println("    Field的name : "+field.name());

      System.out.println("    Field的stringValue : "+field.stringValue());

      System.out.println("    ------------------------------------");

     }

    }

    System.out.println("********************************************************************");

    Date finishTime = new Date();

    long timeOfSearch = finishTime.getTime() - startTime.getTime();

    System.out.println("本次搜索所用的时间为 "+timeOfSearch+" ms");

   

   } catch (CorruptIndexException e) {

    e.printStackTrace();

   } catch (IOException e) {

    e.printStackTrace();

   }

}

}

看上面构造RangeQuery的时候,使用的是同一个Term作为上界和下界,而且inclusive指定为true,这时其实检索的就是termA,结果如下所示:

Document的内部编号为 : 1

Document的得分为 : 0.35136628

Document(编号) 1 的Field的信息:

    Field的name : contents

    Field的stringValue : 谁知道宇宙空间的奥秘,在我们这些人当中?

    ------------------------------------

    Field的name : contents

    Field的stringValue : 宇宙飞船。

    ------------------------------------

    Field的name : contents

    Field的stringValue : 我们的太空宇宙。

    ------------------------------------

********************************************************************

本次搜索所用的时间为 93 ms

含有词条“这些”的Document只有编号为1的满足条件。如果上面程序中inclusive指定为false,表示检索的termA作为上界和下界的开区间,很容易想到,检索的检索一定是空集。

如果修改RangeQuery的构造如下:

RangeQuery rangeQuery = new RangeQuery(termA,termB,false);

查询结果还是空集,要知道:“这些”在字母排序时要在“辩论”之后,而且取的是开区间。

如果修改为:

RangeQuery rangeQuery = new RangeQuery(termA,termB,true);

则只是对两个边界进行检索,结果可能会存在,我的测试结果如下所示:

Document的内部编号为 : 1

Document的得分为 : 0.35136628

Document(编号) 1 的Field的信息:

    Field的name : contents

    Field的stringValue : 谁知道宇宙空间的奥秘,在我们这些人当中?

    ------------------------------------

    Field的name : contents

    Field的stringValue : 宇宙飞船。

    ------------------------------------

    Field的name : contents

    Field的stringValue : 我们的太空宇宙。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息