?

今天看看 ch3, Add search to your Application. 真正開始使用 Lucene search 來搜索你的目標了.

1. 實現一個簡單的search feature

?? 在本章中只限于討論簡單Lucene 搜索API, 有下面幾個相關的類:

?Lucene 基本搜索API:

功能

IndexSearcher搜索一個index的入口.所有的searches都是通過IndexSearcher 實例的幾個重載的方法實現的.
Query (and subclasses)各個子類封裝了特定搜索類型的邏輯(logic),Query實例傳遞給IndexSearcher的search方法.
QueryParser 處理一個可讀的表達式,轉換為一個具體的Query實例.
Hits 包含了搜索的結果.有IndexSearcher的search函數返回.

下面我們來看幾個書中的例子:

LiaTestCase.java? 一個繼承自TestCase 并且擴展了TestCase的類, 下面的幾個例子都繼承自該類.

01?package?lia.common;
02?
03?import?junit.framework.TestCase;
04?import?org.apache.lucene.store.FSDirectory;
05?import?org.apache.lucene.store.Directory;
06?import?org.apache.lucene.search.Hits;
07?import?org.apache.lucene.document.Document;
08?
09?import?java.io.IOException;
10?import?java.util.Date;
11?import?java.text.ParseException;
12?import?java.text.SimpleDateFormat;
13?
14?/**
15??*?LIA?base?class?for?test?cases.
16??*/
17?public?abstract?class?LiaTestCase?extends?TestCase?{
18???private?String?indexDir?=?System.getProperty("index.dir");? // 測試 index 已經建立好了
19???protected?Directory?directory;
20?
21???protected?void?setUp()?throws?Exception?{
22?????directory?=?FSDirectory.getDirectory(indexDir,?false);
23???}
24?
25???protected?void?tearDown()?throws?Exception?{
26?????directory.close();
27???}
28?
29???/**
30????*?For?troubleshooting 為了 解決問題的方法
31????*/
32???protected?final?void?dumpHits(Hits?hits)?throws?IOException?{
33?????if?(hits.length()?==?0)?{
34???????System.out.println("No?hits");
35?????}
36?
37?????for?(int?i=0;?i?<?hits.length();?i++)?{
38???????Document?doc?=?hits.doc(i);
39???????System.out.println(hits.score(i)?+?":"?+?doc.get("title"));
40?????}
41???}
42?
43???protected?final?void?assertHitsIncludeTitle(
44???????????????????????????????????????????Hits?hits,?String?title)
45?????throws?IOException?{
46?????for?(int?i=0;?i?<?hits.length();?i++)?{
47???????Document?doc?=?hits.doc(i);
48???????if?(title.equals(doc.get("title")))?{
49?????????assertTrue(true);
50?????????return;
51???????}
52?????}
53?
54?????fail("title?'"?+?title?+?"'?not?found");
55???}
56?
57???protected?final?Date?parseDate(String?s)?throws?ParseException?{
58???????return?new?SimpleDateFormat("yyyy-MM-dd").parse(s);
59???}
60?}

? I.搜索一個特定的Term 和利用QueryParser 解析用戶輸入的表達式

? 要利用一個特定的term搜索,使用QueryTerm就可以了,單個term 尤其適合Keyword搜索. 解析用戶輸入的表達式可以更適合用戶的使用方式,搜索表達式的解析有QueryParser來完成.如果表達式解析錯誤 會有異常拋出, 可以取得相信的錯誤信息 以便給用戶適當的提示.在解析表達式時,還需要一個Analyzer 來分析用戶的輸入, 并根據不同的Analyzer來生產相應的Term然后構成Query實例.

下面看個例子吧:BasicSearchingTest.java

01?package?lia.searching;
02?
03?import?lia.common.LiaTestCase;
04?import?org.apache.lucene.analysis.SimpleAnalyzer;
05?import?org.apache.lucene.document.Document;
06?import?org.apache.lucene.index.Term;
07?import?org.apache.lucene.queryParser.QueryParser;
08?import?org.apache.lucene.search.Hits;
09?import?org.apache.lucene.search.IndexSearcher;
10?import?org.apache.lucene.search.Query;
11?import?org.apache.lucene.search.TermQuery;
12?
13?public?class?BasicSearchingTest?extends?LiaTestCase?{
14?
15???public?void?testTerm()?throws?Exception?{
16?????IndexSearcher?searcher?=?new?IndexSearcher(directory);
17?????Term?t?=?new?Term("subject",?"ant");??????????????? // 構造一個Term
18?????Query?query?=?new?TermQuery(t);
19?????Hits?hits?=?searcher.search(query);???????????????? // 搜索
20?????assertEquals("JDwA",?1,?hits.length());???????????? //測試結果
21?
22?????t?=?new?Term("subject",?"junit");
23?????hits?=?searcher.search(new?TermQuery(t));??????????????????
24?????assertEquals(2,?hits.length());
25?
26?????searcher.close();
27???}
28?
29???public?void?testKeyword()?throws?Exception?{? // 測試關鍵字搜索
30?????IndexSearcher?searcher?=?new?IndexSearcher(directory);
31?????Term?t?=?new?Term("isbn",?"1930110995");???????????????? // 關鍵字 term
32?????Query?query?=?new?TermQuery(t);
33?????Hits?hits?=?searcher.search(query);
34?????assertEquals("JUnit?in?Action",?1,?hits.length());
35???}
36?
37???public?void?testQueryParser()?throws?Exception?{? // 測試 QueryParser.
38?????IndexSearcher?searcher?=?new?IndexSearcher(directory);
39?
40?????Query?query?=?QueryParser.parse("+JUNIT?+ANT?-MOCK",
41?????????????????????????????????????"contents",
42?????????????????????????????????????new?SimpleAnalyzer());? // 通過解析搜索表達式 返回一個Query實例
43?????Hits?hits?=?searcher.search(query);
44?????assertEquals(1,?hits.length());
45?????Document?d?=?hits.doc(0);
46?????assertEquals("Java?Development?with?Ant",?d.get("title"));
47?
48?????query?=?QueryParser.parse("mock?OR?junit",
49???????????????????????????????"contents",
50???????????????????????????????new?SimpleAnalyzer());?????????????
// 通過解析搜索表達式 返回一個Query實例
51?????hits?=?searcher.search(query);
52?????assertEquals("JDwA?and?JIA",?2,?hits.length());
53???}
54?}