关于范围查询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的内部编号为 : 1Document的得分为 : 0.35136628Document(编号) 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的内部编号为 : 1Document的得分为 : 0.35136628Document(编号) 1 的Field的信息: Field的name : contents Field的stringValue : 谁知道宇宙空间的奥秘,在我们这些人当中? ------------------------------------ Field的name : contents Field的stringValue : 宇宙飞船。 ------------------------------------ Field的name : contents Field的stringValue : 我们的太空宇宙。 ------------------------------------********************************************************************本次搜索所用的时间为 93 ms
