建立數值索引是用 NumericField 取代原本的 Field,查詢數值索引時改用 NumericRangeQuery。
另外,除了純數值欄位外,還有一種文數字混合的欄位,也就是字串裡有數值存在,這可以當作是一種文字來處理。
public class RangeTestCase extends TestCase { private static final Version VERSION = Version.LUCENE_36; private static final String F_TITLE = "title"; private static final String F_PRICE = "price"; private static final String F_PUBLICATION_TIME = "pTime"; private Directory directory = new RAMDirectory(); private IndexWriter writer; private IndexReader reader; private IndexSearcher searcher; @Override protected void setUp() throws Exception { super.setUp(); // create index this.writer = this.createWriter(); // this.writer.setInfoStream(System.out); System.out.println("addDocument..."); this.writer.addDocument(this.createDocument("Lucene in action", 44.95, new Date(104, 11, 1))); this.writer.addDocument(this.createDocument("Lucene in action, 2 Edition", 49.99, new Date(110, 6, 28))); this.writer.addDocument(this.createDocument("Spring in action", 7.89, new Date(104, 11, 1))); this.writer.addDocument(this.createDocument("Spring in action, 2 Edition", 11.44, new Date(107, 7, 23))); this.writer.addDocument(this.createDocument("Spring in action, 3 Edition", 49.99, new Date(111, 5, 29))); System.out.println("commit..."); // 資料太多時,可以分批 commit // commit後(沒有close)就可以使用 IndexReader this.writer.commit(); // 沒有 close 或 commit,不能使用 IndexReader // this.closeWriter(); } private Document createDocument(String title, double price, Date date) { Document doc = new Document(); // 文字欄位用 Field doc.add(new Field(RangeTestCase.F_TITLE, title, Field.Store.YES, Field.Index.ANALYZED)); // 數值欄位用 NumericField doc.add(new NumericField(RangeTestCase.F_PRICE, Field.Store.YES, true).setDoubleValue(price)); // 日期欄位一樣是用 NumericField,只要轉成 long 值就可以了 doc.add(new NumericField(RangeTestCase.F_PUBLICATION_TIME, Field.Store.YES, true).setLongValue(date.getTime())); return doc; } @Override protected void tearDown() throws Exception { super.tearDown(); this.closeWriter(); this.closeSearcher(); } /** * 查詢文字中的數字 */ public void testTextWithNumberQuery() { System.out.println("testTextWithNumberQuery..."); try { // 必須用 WhitespaceAnalyzer 或 StandardAnalyzer // 不可用會丟掉數字的 SimpleAnalyzer 或 StopAnalyzer IndexSearcher searcher = this.createSearcher(); TopDocs hits = searcher.search(new TermQuery(new Term( RangeTestCase.F_TITLE, "3")), 100); this.showDocuments(searcher, hits); assertEquals(1, hits.totalHits); } catch (IOException e) { Assert.fail(e.getMessage()); } } /** * 查詢數值欄位,包含起訖 */ public void testNumericRangeQueryInclusive() { System.out.println("testNumericRangeQueryInclusive..."); try { // 查詢 double NumericRangeQuery<Double> q = NumericRangeQuery.newDoubleRange( RangeTestCase.F_PRICE, 7.89, 44.95, true, true); IndexSearcher searcher = this.createSearcher(); TopDocs hits = searcher.search(q, 100); this.showDocuments(searcher, hits); assertEquals(3, hits.totalHits); } catch (IOException e) { Assert.fail(e.getMessage()); } } /** * 查詢數值欄位,不包含起訖 */ public void testNumericRangeQueryExclusive() { System.out.println("testNumericRangeQueryExclusive..."); try { // 查詢 double NumericRangeQuery<Double> q = NumericRangeQuery.newDoubleRange( RangeTestCase.F_PRICE, 7.89, 44.95, false, false); IndexSearcher searcher = this.createSearcher(); TopDocs hits = searcher.search(q, 100); this.showDocuments(searcher, hits); assertEquals(1, hits.totalHits); } catch (IOException e) { Assert.fail(e.getMessage()); } } /** * 查詢日期欄位,包含起訖 */ public void testDateRangeQuery() { System.out.println("testDateRangeQuery..."); try { // 查詢 long 日期 NumericRangeQuery<Long> q = NumericRangeQuery.newLongRange( RangeTestCase.F_PUBLICATION_TIME, new Date(107, 7, 23).getTime(), new Date(110, 6, 28).getTime(), true, true); IndexSearcher searcher = this.createSearcher(); TopDocs hits = searcher.search(q, 100); this.showDocuments(searcher, hits); assertEquals(2, hits.totalHits); } catch (IOException e) { Assert.fail(e.getMessage()); } } /** * 倒出文章 */ private void showDocuments(IndexSearcher searcher, TopDocs hits) throws CorruptIndexException, IOException { Document d; for (ScoreDoc sd : hits.scoreDocs) { d = searcher.doc(sd.doc); System.out.println(d.get(F_TITLE) + " - " + d.get(F_PRICE) + " - " + new Date(Long.parseLong(d.get(F_PUBLICATION_TIME)))); } } private IndexWriter createWriter() throws CorruptIndexException, LockObtainFailedException, IOException { IndexWriterConfig config = new IndexWriterConfig(RangeTestCase.VERSION, new StandardAnalyzer(RangeTestCase.VERSION)); config.setOpenMode(OpenMode.CREATE); return new IndexWriter(this.directory, config); } private IndexSearcher createSearcher() throws CorruptIndexException, IOException { return new IndexSearcher(this.createReader()); } private IndexReader createReader() throws CorruptIndexException, IOException { return IndexReader.open(this.directory); } private void closeWriter() { if (this.writer != null) { try { this.writer.close(); } catch (IOException e) { e.printStackTrace(); } } } private void closeSearcher() { this.closeReader(); if (this.searcher != null) { try { this.searcher.close(); } catch (IOException e) { e.printStackTrace(); } } } private void closeReader() { if (this.reader != null) { try { this.reader.close(); } catch (IOException e) { e.printStackTrace(); } } } }---
沒有留言:
張貼留言