首页 > 代码库 > Lucene 4.* QueryParser Range Searcher (范围查询)

Lucene 4.* QueryParser Range Searcher (范围查询)

 

 由于Lucene4.9.1的QueryParser支持类似Solr的范围检索( FL:[ 111 TO 222] ) 但是实际中会出现不准确的现象。

这是由于QueryParser 把范围查询当做String类型。而无论索引时使用LongField 和 TextField 都会出现不准确问题。

解决办法是手动将范围检索改成long类型或int类型。

 

1 自定义QueryParser 。

public class RangeQueryParser extends QueryParser {    public RangeQueryParser(Version matchVersion, String f, Analyzer a) {        super(matchVersion, f, a);    }    @Override    protected Query getRangeQuery(String field, String part1, String part2, boolean arg3, boolean arg4) throws ParseException {        try {            long num1 = Long.parseLong(part1);            long num2 = Long.parseLong(part2);            return NumericRangeQuery.newLongRange(field, num1, num2, true, true);        } catch (NumberFormatException e) {            throw new ParseException(e.getMessage());        }    }}

 

2 使用方法:

 

package org.bidlink.index;import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field.Store;import org.apache.lucene.document.LongField;import org.apache.lucene.document.TextField;import org.apache.lucene.index.DirectoryReader;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.queryparser.classic.QueryParser;import org.apache.lucene.search.IndexSearcher;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.util.Version;import org.wltea.analyzer.lucene.IKAnalyzer;import com.bidlink.general.index.RangeQueryParser;import com.bidlink.general.index.SearcherCallBack;import com.bidlink.general.index.WordBankConst;public class TestIndex {    public void index() throws Exception {        Directory d = FSDirectory.open(new File("Index"));        IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_4_9, new IKAnalyzer());        IndexWriter iw = new IndexWriter(d, iwc);        Document doc = new Document();        doc.add(new TextField("WORD", "测试北京市第102个", Store.YES));        doc.add(new LongField("ENDDATE", 1234556L, Store.YES));        iw.addDocument(doc);        iw.commit();        iw.close();    }    public void search(String fl, String word, SearcherCallBack callBack) throws Exception {        Directory d = FSDirectory.open(new File("Index"));        IndexReader r = DirectoryReader.open(d);        IndexSearcher s = new IndexSearcher(r);        callBack.maxDocs = s.getIndexReader().maxDoc();        callBack.numDocs = s.getIndexReader().numDocs();        QueryParser qp = new RangeQueryParser(Version.LUCENE_4_9, fl, new IKAnalyzer());        qp.setDefaultOperator(QueryParser.Operator.AND);        try {            TopDocs tdocs = s.search(qp.parse(word), 1000);            callBack.numFound = tdocs.totalHits;            ScoreDoc scoreDocs[] = tdocs.scoreDocs;            for (ScoreDoc sDoc : scoreDocs) {                int docNumber = sDoc.doc;                Document doc = s.doc(docNumber);                callBack.process(doc);            }        } catch (Exception e) {            e.printStackTrace();        }    }    public static void main(String[] args) throws Exception {        SearcherCallBack s = new SearcherCallBack() {            @Override            public void process(Document doc) {                // System.out.println(doc.getField(WordBankConst.ID).stringValue());                System.out.println(doc.getField(WordBankConst.WORD).stringValue());                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");                String date = sdf.format(new Date(Long.parseLong(doc.getField(WordBankConst.ENDDATE).stringValue())));                System.out.println(Long.parseLong(doc.getField(WordBankConst.ENDDATE).stringValue()) + "   " + date);            }        };        TestIndex index = new TestIndex();        // index.index();        index.search("", "WORD:地铁  AND ENDDATE:[1111 TO 222222222222 ]", s);        System.out.println("Doc numFound :  " + s.numFound + "  Max Doc num :" + s.maxDocs);    }}

 

Lucene 4.* QueryParser Range Searcher (范围查询)