Lucene筆記27-Lucene的使用-自定義QueryParser解決日期和數字範圍問題
阿新 • • 發佈:2018-11-29
一、需求說明
Lucene提供的getRangeQuery(String field, String part1, String part2, boolean inclusive)方法支援的是String,假設我們需要對數字範圍查詢,那麼就需要我們自己來改寫了。
二、程式碼實現
重寫getRangeQuery()方法。searchByQuery()方法將傳入的查詢字串進行parse,根據轉化後的樣式,呼叫到了被重寫的getRangeQuery()方法,從而走了裡面的邏輯完成查詢。
package com.wsy; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.*; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.regex.Pattern; public class CustomParser extends QueryParser { private static Directory directory; private static IndexReader indexReader; private static Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35); static { try { directory = FSDirectory.open(new File("E:\\Lucene\\IndexLibrary")); indexReader = IndexReader.open(directory); } catch (IOException e) { e.printStackTrace(); } } public CustomParser(Version matchVersion, String f, Analyzer a) { super(matchVersion, f, a); } @Override protected Query getRangeQuery(String field, String part1, String part2, boolean inclusive) throws ParseException { if (field.equals("size")) { return NumericRangeQuery.newIntRange(field, Integer.parseInt(part1), Integer.parseInt(part2), inclusive, inclusive); } else if (field.equals("date")) { Pattern pattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}"); if (pattern.matcher(part1).matches() && pattern.matcher(part2).matches()) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); try { long start = simpleDateFormat.parse(part1).getTime(); long end = simpleDateFormat.parse(part2).getTime(); return NumericRangeQuery.newLongRange(field, start, end, inclusive, inclusive); } catch (java.text.ParseException e) { e.printStackTrace(); } } else { throw new ParseException("要檢索的日期格式不對,請使用yyyy-MM-dd格式"); } } return super.getRangeQuery(field, part1, part2, inclusive); } public void searchByQuery(String value) { try { CustomParser customParser = new CustomParser(Version.LUCENE_35, "content", analyzer); Query query = customParser.parse(value); System.out.println("query:\t" + query); IndexSearcher indexSearcher = new IndexSearcher(indexReader); TopDocs topDocs = indexSearcher.search(query, 100); ScoreDoc[] scoreDocs = topDocs.scoreDocs; SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (ScoreDoc scoreDoc : scoreDocs) { Document document = indexSearcher.doc(scoreDoc.doc); // 依次輸出文件id,文件得分,文件名字,文件路徑,文件大小,文件修改時間 System.out.println(scoreDoc.doc + "-->" + scoreDoc.score + "-->" + document.get("fileName") + "-->" + document.get("path") + "-->" + document.get("size") + "-->" + simpleDateFormat.format(new Date(Long.valueOf(document.get("date"))))); } indexSearcher.close(); } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { System.err.println(e.getMessage()); } } public static void main(String[] args) { CustomParser customParser = new CustomParser(Version.LUCENE_35, "content", analyzer); // 查詢size是300到800的 customParser.searchByQuery("size:[300 TO 800]"); // 查詢date是2018-01-01到2018-12-31的 customParser.searchByQuery("date:[2018-01-01 TO 2018-12-31]"); } }