從知道Hadoop起就聽過Lucene的大名,但是一直沒有抽出時間好好學習下,最近有了段空閑時間,決定把這些東西補一下,不求知根知底,但求大致了解。
Lucene的概要描述就不多復制了,總之使用它可以快速創建索引,并進行檢索,是一個設計良好的框架。
Lucene的使用十分簡單,網上下載Lucene包,導入工程基本上就可以使用了,我用的是Lucene4.2的包,下載下來解壓后有以下這些目錄:

簡單的Lucene程序,只用引入core下面的lucene-core.jar以及analysis下面common里面的lucene-analyzers-common.jar就可以了。
Lucene設計的比較好,高級用戶可以進行細致化的定制,但是如果初級用戶(譬如我)使用的話,也可以很方面的使用,這里就把我的例子貼出來吧。
1 /** 2 * 針對某個文件夾下(不包括子文件夾)所有的txt文件建立索引,存放在該文件夾下的index文件夾中。 3 * 4 * @param rootPath 5 */ 6 public static void buildIndex(String rootPath) throws IOException { 7 //指定索引文件目錄 8 Directory indexDir = FSDirectory.open(new File(rootPath + "/index")); 9 File dataDir = new File(rootPath);10 File[] dataFiles = dataDir.listFiles();11 //構造分析器12 Analyzer luceneAnalyzer = new StandardAnalyzer(Version.LUCENE_42);13 //使用分析器構造索引生成器14 IndexWriter indexWriter = new IndexWriter(indexDir, new IndexWriterConfig(Version.LUCENE_42, luceneAnalyzer));15 indexWriter.deleteAll();16 //開始生成索引17 for (int i = 0; i < dataFiles.length; i++) {18 if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")) {19 Document document = new Document();20 //以文件名作為path域的內容,Field.Store.YES表示會將其存儲到索引中,從而可以直接通過索引查詢到內容21 document.add(new StringField("path", dataFiles[i].getCanonicalPath(), Field.Store.YES));22 //以文件內容作為contents域的內容,Field.Store.NO表示不將其存儲到索引中,這樣的話,可以根據其關鍵字查詢到索引,但是查詢不到具體內容。23 document.add(new TextField("contents", FileUtils.readFileToString(dataFiles[i], "GBK"), Field.Store.NO));24 indexWriter.addDocument(document);25 }26 }27 //commit和close合二為一。28 indexWriter.close();29 }30 /**31 * 根據索引進行檢索32 *33 * @param indexDir 索引文件存放位置34 * @param keyWord 索引關鍵字35 * @param numberOfRecords 需要查詢出幾條記錄36 */37 public static List<String> search(String indexDir, String keyword, int numberOfRecords) throws IOException {38 //打開索引文件39 Directory indexDirectory = FSDirectory.open(new File(indexDir));40 DirectoryReader ireader = DirectoryReader.open(indexDirectory);41 //構造索引查詢器42 IndexSearcher isearcher = new IndexSearcher(ireader);43 //構造查詢語句44 Query query = new TermQuery(new Term("contents", keyword));45 //進行查詢46 ScoreDoc[] hits = isearcher.search(query, null, numberOfRecords).scoreDocs;47 List<String> result = new ArrayList<String>();48 //遍歷查詢結果49 for (ScoreDoc scoreDoc : hits)50 result.add(isearcher.doc(scoreDoc.doc).get("path"));51 return result;52 }完成上面的代碼后,就可以對對某個文件夾下的所有文件構建索引并進行查詢了,經測試,對英文文件的索引是相當給力的。
這里啰嗦一下自己對Lucene原理的理解,Lucene建立索引的過程為:
1 對需要建立索引的內容進行分詞,得到關鍵字。
2 對關鍵字進行加工,加工過程包括:過濾,過濾掉語氣助詞,如and、or、to等;大小寫轉化,因為人們可能希望查詢"Computer"的時候,可以查詢到"computer"、"COMPUTER"等相關詞;詞態轉化,如希望在查詢"want"的時候,可以查詢到"wants","wanted"等等。
3 根據關鍵字建立索引,即記錄某個關鍵字在哪些文檔中出現過。
大致過程就是這樣,更細節的優化還沒有看,想著等將來需要深層次使用的時候再去看吧。
上面這些步驟完成后,就可以方面的進行查詢了。
如果大家比較細心的話,就會發現我上面專門強調“對英文文件的索引是相當給力的”,也就說明對中文文件的索引相當不給力,這是因為英文分詞相對比較容易,根據空白字符和標點符號基本上就可以分詞了,但是中文分詞比較有難度(可以百度“清明時節雨紛紛 斷詞”,然后自己體會),因此如果需要對中文文件建立索引時,需要使用其他的分詞包,做的比較出色的有Lucene自帶的SmartCN和IKAnalyzer。這兩個分詞包的使用也比較簡單:
需要使用SmartCN時,引入SmartCN的包(在analysis下面的smartcn下),然后將上面代碼的第12行改為:
1 Analyzer luceneAnalyzer = new SmartChineseAnalyzer(Version.LUCENE_42);
即可。
需要使用IKAnalyzer時,引入IKAnalyzer的包(網上自行搜索),然后將上面代碼的第12行改為:
1 Analyzer luceneAnalyzer = new IKAnalyzer();
即可。
再次感謝面向對象這個偉大的發明!
以上就是我對Lucene當前的理解了,如果項目中真正用到Lucene時,再深入學習吧。
本文涉及代碼已在Oschina的Git上共享了,鏈接為:http://git.oschina.net/xdxn/Test
參考文獻:
開源中文分詞框架分詞效果對比smartcn與IKanalyzer
Lucene 工作原理
新聞熱點
疑難解答