【轉載】Lucene學習筆記(二)

二、第一個"搜索引擎":
大綱:1.Lucene下載包結構簡介
2.使用Lucene爲本地文件建立索引
3.測試性搜索
4.改進的意見

1.初識Lucene

1.1 Lucene的下載:可到Apache官網http://lucene.apache.org下載Lucene開發工具包,這裏我們用1.4.3穩定版本

1.2 Lucene的源碼包結構:

1.2.1 analysis包:該包下的源碼類主要用於對需要建立索引的文件內容進行分詞、過濾等操作。
除了標準的由JavaCC生成的分詞器源代碼外,該包中還包含了對德語和俄語分詞器與過濾器的支持,ru包是俄語支持包,de包是德語支持包。

1.2.2 standard包:是Lucene的標準分詞器包,同時還保留了使用JavaCC生成分詞器時的.jj腳本(關於JavaCC的相關內容後面章節會介紹)

1.2.3 document包:主要用於向Lucene提供對Document和Field操作的支持。(Document和Field後面章節會涉及)

1.2.4 index包:是Lucene最重要的一個包,用於向Lucene提供建立索引時各種操作的支持。

1.2.5 queryParser包:用於向Lucene提供檢索時的分析支持。搜索引擎除了要在建立索引的時候對大量文本進行分析外,
還要對用戶輸入的查詢關鍵字進行分析,以便建立Lucene中正確的搜索條件(分析處理用戶輸入的關鍵字,
和要搜索的索引中的某個字段(就是Document中的Field的key))進行綁定,解析出一個Query條件對象,

1.2.6 search包: 負責檢索的類包,調用該包下的相應的類方法,就可以完成搜索並返回結果集。

1.2.7 store包:主要用於提供對索引存儲的支持。它裏面的FSDirectory和RAMDirectory類是Lucene中最爲常用的兩個索引目錄,
後面會有對這兩個類的講解。

1.2.8 util包:爲Lucene提供了一些工具類和常量類的支持。

2.爲本機的文件創建索引:因爲要應用所以要創建一個工程,使用Lucene的基本功能,我們只需想工程的lib中導入lucene.jar包即可!

2.1 首先選擇用於創建索引的本地文件:"C://lucene_source"中有a.txt、b.txt、c.txt、d.txt文件,
內容都很簡單:中華人民共和國、人民共和國、人民、共和國

2.2 指定存放索引文件的目錄:"C://lucene_index"

2.3 建立索引:具體代碼後邊會講解------------下邊"**注意"中是對分詞器分詞功能的說明,還提供了中文分詞的解決方案!!
public class CreateLuceneIndex {
//定義一個索引寫入器
private IndexWriter indexWriter;
//缺省構造方法*/
public CreateLuceneIndex() {
/*
初始化寫入器,指定保存索引的目錄,指定一個標準的分詞器 true代表每次都要保存最新的索引信息到指定的目錄,如果已經存在那麼先刪除

**注意:標準的分詞器對中文的支持並不是很好,他只能單個字建立索引,例如:"中華人民共和國"這段話,
會被分成"中"、"華"、"人"、"民"、"共"、"和"、"國",而不是我們期望的"中華"、"人民"、"共和國"
還有一種是CJKAnalyzer類(需要單獨下載JAR包)是進行二分法分詞,對於上面的"中華人民共和國",會被分成"中華"、"華人"、"人民"、"民共"、"共和"、"和國"
還有一種是MMAnalyzer類(需要單獨下載JAR包)是詞典分詞中的極易分詞器,將會分成我們期望的"中華"、"人民"、"共和國",對於詞典分詞還有一種分詞器是庖丁分詞器(也要單獨下載,庖丁分詞和極易分詞都可以很好的解決中文索引問題)
*/
indexWriter = new IndexWriter(Constants.INDEX_DESC_PATH, new StandardAnalyzer(), true);
}
//將指定的要建立索引的文件包裝成Document對象 然後返回包裝好的Document對象
public Document getDocument(File file) {
// 創建一個預接收數據的Document對象
Document document = new Document();
// 創建一個Read讀取文件的流對象
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
/*
* 將文件中的內容保存到Field對象,因爲Field對象是一個鍵值對,所以要指定一個Key鍵 Field.Text("content",
* bufferedReader)方法是建立Field對象而且創建索引,但是不存儲索引(由API得知)
*/
document.add(Field.Text("content", bufferedReader));
//得到文件的絕對路徑
document.add(Field.Keyword("path", file.getAbsolutePath()));
//返回封裝好的Document對像
return document;
}
//核心方法:爲指定目錄的文檔建立索引,然後將索引寫入到磁盤
public void writerToIndex() {
// 關聯到C://lucene_source目錄
File file = new File("C://lucene_source");
// 因爲file對象此時代表的是一個目錄
if (file.isDirectory()) {
// 得到目錄中的所有文件名(包含擴展名)
String[] fileNames = file.list();
for (int i = 0; i < fileNames.length; i++) {
File source = new File(file, fileNames[i]);
// 將文件轉換成Document對象
Document document = getDocument(source);
System.out.println("正在爲文件 " + fileNames[i] + " 建立索引...");
indexWriter.addDocument(document);
}
}
}
//關閉寫入器
public void close(){
//關閉寫入器,最後將索引寫入磁盤
}
//主方法入口點
public static void main(String[] args) {
// 創建一個實例對象:目的是可以調用構造方法和調用類內的相應方法
CreateLuceneIndex createLuceneIndex = new CreateLuceneIndex();
//創建索引開始時間
Date start = new Date();
//寫入索引到磁盤
createLuceneIndex.writerToIndex();
//創建索引結束時間
Date end = new Date();
System.out.println("建立索引耗時: " + (end.getTime() - start.getTime()) + "毫秒!");
//關閉索引寫入器
createLuceneIndex.close();
}
}

2.4 開始搜索:具體代碼後邊會講解
public class SearchMachine {
// 創佳搜索器對象
private IndexSearcher indexSearcher;
// 創建Lucene格式的查詢條件對象
private Query query;

//缺省構造方法
public SearchMachine() {
// 初始化搜索器:並指定保存索引的目錄
indexSearcher = new IndexSearcher(Constants.INDEX_DESC_PATH);
}
//根據指定的用戶輸入的查詢關鍵字查詢結果
public Hits getSearchResults(String queryKey) {
//定義接收結果的Hits對象
Hits hits = null;
//根據查詢關鍵字、字段名稱、分詞器,解析關鍵字,並封裝成Lucene格式的對對應字段(content)的查詢條件
query = QueryParser.parse(queryKey, "content", new StandardAnalyzer());
//搜索開始時間
Date start = new Date();
//開始搜索
hits = indexSearcher.search(query);
//搜索結束時間
Date end = new Date();
System.out.println("搜索完成,用時: " + (end.getTime() - start.getTime()) + "毫秒!");
//返回結果
return hits;
}
//打印結果集
public void printSearchResults(Hits hits){
//判斷是否結果爲空
if(hits.length() == 0){
System.out.println("對不起,沒有找到您想要的搜索結果!");
return;
}
//循環輸出檢索結果的每個Document對象中包裝的內容
for (int i = 0; i < hits.length(); i++) {
//得到結果集中的Document對象
Document document = hits.doc(i);
System.out.println("這是第 " + (i+1) + "個被檢索到的文件,文件名爲: " + document.get("path"));
}
}
//搜索功能的入口
public static void main(String[] args) {
//創建對象:目的是調用構造方法,和可以調用本類中的其他方法
SearchMachine searchMachine = new SearchMachine();
//用"中華"作爲用戶輸入的搜索關鍵字進行查找,打印結果
searchMachine.printSearchResults(searchMachine.getSearchResults("中華"));
System.out.println("-------------------------------------------------");
//用"人民"作爲用戶輸入的搜索關鍵字進行查找,打印結果
searchMachine.printSearchResults(searchMachine.getSearchResults("人民"));
System.out.println("-------------------------------------------------");
//用"共和國"作爲用戶輸入的搜索關鍵字進行查找,打印結果
searchMachine.printSearchResults(searchMachine.getSearchResults("共和國"));
System.out.println("-------------------------------------------------");
}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章