lucene簡介

Lucene3.6 入門指南

目錄

 

一、 簡介


Lucene是什麼:Lucene是apache軟件基金會jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,即它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此爲基礎建立起完整的全文檢索引擎。

 

Lucene是一個基於Java的全文搜索,不是一個完整的搜索應用,而是一個代碼庫和API,可以方便地爲應用提供搜索功能。 實際上Lucene的功能就是將開發人員提供的若干個字符串建立索引,然後提供一個全文搜索服務,用戶將搜索的關鍵詞提供給搜索服務,搜索服務告訴用戶關鍵詞出現的各字符串。

 

二、 基本流程


可見,lucene包含兩部分:建立索引和搜索服務。建立索引是將源(本質是字符串)寫入索引或者將源從索引中刪除;進行搜索是向用戶提供全文搜索服務,用戶可以通過關鍵詞定位源。

1. 建立索引的流程

  • 使用analyzer處理源字符串,包括:分詞,即分成一個個單詞;去除stopword(可選)。
  • 將源中的有效信息以不同Field的形式加入Document中,並把Document加入索引,從而在索引中記錄有效的Field。
  • 將索引寫入存儲器(內存或磁盤)。

2. 檢索的流程

  • 用戶提供搜索關鍵詞,經過analyzer處理。
  • 對處理後的關鍵詞搜索索引找出對應的Document。
  • 用戶根據需要從找到的Document中提取需要的Field。 

 

三、 基本概念


1. Analyzer

Analyzer的作用是分詞,並去除字符串中的無效詞語。

分詞的目的是把字符串按某種語義規則劃分爲若干個詞。英文中比較容易實現分詞,因爲英文本身就是以單詞爲單位,已經用空格分開;而中文則必須以某種方法將連成一片的句子劃分成一個個詞。 無效詞語,如英文中的“of”、“the”和中文中的“的”、“地”等,這些詞語在文章中大量出現。但是本身不包含關鍵信息,去掉後有利於縮小索引文件、提高命中率和執行效率。

2. Document

用戶提供的源可以是文本文件、字符串或者數據庫表中的一條記錄等。一個源字符串經過索引之後,以一個Document的形式存儲在索引文件中。搜索服務的結果也是以Document列表的形式返回。

3. Field

一個Document可以包含多個信息域,如一篇文章可以包含“標題”、“正文”、“最後修改時間”等信息域,這些信息域以Field的形式保存在Document中。

Field有兩個屬性:存儲和索引。存儲屬性可以控制是否對這個Field進行存儲;索引屬性可以控制是否對該Field進行索引。這似乎多此一舉,但事實上對這兩個屬性的正確組合很重要。 

下面舉例說明:一篇文章需要對標題和正文進行全文搜索,所以把這兩個Field的索引屬性設置爲真;同時希望能直接從搜索結果中提取文章標題,所以把標題Field的存儲屬性設置爲真。但是正文Field太大了,爲了縮小索引文件,將正文Field的存儲屬性設置爲假,需要訪問時再直接讀取文件正文;希望能從搜索結果中提取最後修改時間;但是不需要對它進行搜索,所以把最後修改時間Field的存儲屬性設置爲真,索引屬性設置爲假。

Field的兩個屬性禁止全爲假的情況因爲這對建立索引沒有意義。

4. segment

建立索引時,並不是每個document都馬上添加到同一個索引文件,它們首先被寫入到不同的小文件,然後再合併成一個大索引文件,每個小文件都是一個segment。

5. term

term表示文檔的一個詞,是搜索的最小單位。term由兩部分組成:所表示的詞語和這個詞語所出現的field。

6. token

token是term的一次出現,它包含trem文本和相應的起止偏移,以及一個類型字符串。一句話中可以出現多次相同的詞語,它們都用同一個term表示,但是用不同的token,每個token標記該詞語出現的位置。 

 

四、 Lucene的組成結構


Lucene包括core和sandbox兩部分,其中core是lucene的核心,sandbox包含了一些附加功能,如highlighter、各種分析器等。 Lucene core包含8個包:analysis、collation、document、index、queryParser、search、store、util。

1. analysis包

Analysis提供自帶的各種Analyzer,如按空白字符分詞的WhitespaceAnalyzer,添加了stopword過濾的StopAnalyzer,支持中文分詞的SmartChineseAnalyzer,以及最常用的StandardAnalyzer。

2. collation包

包含collationKeyFilter和collationKeyAnalyzer兩個相同功能的類,將所有token轉換爲CollationKey,並將CollationKey與IndexableBinaryStringTools一起編碼存儲爲一個term。

3. document包

document包中是Document相關的各種數據結構,如Document類、Field類等。

4. index包

index包中是索引的讀寫操作類,常用的是對索引文件的segment進行寫、合併和優化的IndexWriter類和對索引進行讀取和刪除操作的IndexReader類。IndexWriter只關心如何將索引寫入一個個segment並將它們合併優化;IndexReader關注索引文件中各個文檔的組織形式。

5. queryParser包

queryParser包中是解析查詢語句相關的類(常用的是QueryParser類)以及Token類。

6. search包

search包中是從索引中進行搜索的各種不同的Query類(如TermQuery、BooleanQuery等)和搜索結果集Hits類。

7. store包 store包中是索引的存儲相關類,如Directory類定義了索引文件的存儲結構,FSDirectory是存儲在文件系統(即磁盤)中的索引存儲類,RAMDirectory爲存儲在內存中的索引存儲類,MmapDirectory爲使用內存映射的索引存儲類。

8. util包 util包中是公共工具類,例如時間和字符串之間的轉換工具。

 

五、 環境搭建


下載:

  1. http://lucene.apache.org/core/downloads.html
  2. http://mirror.bjtu.edu.cn/apache/lucene/java/3.6.1/lucene-3.6.1.zip

把lucene-core-3.6.1.jar加到項目中。

 

快速入門(Helloworld)

在開始helloworld之前,以lucene創建索引的流程輔助我們來了解幾個概念。

  1. 信息源:要採集,必須有信息源,在這裏我們就以讀取硬盤中的文件(File)充當信息源。
  2. 加工:要把採集的信息,以lucene規定的形式存放到索引庫中,所以要創建相應的文檔(Document)對象。在這個文檔中,我們要存放哪些信息才能達到完整且闢免垃圾信息,例如網頁,我們可以要存儲的是他的標題、內容、URL等,那些廣告是不用存儲的。在這裏我們用到Field來存儲各項目內容。
  3. 分析:對於加工好的了文檔,我們是不是應該對其進行分詞,答案是肯定的。用什麼分詞器呢?對英文和中文使用的分詞器有可能不一樣吧,這個得看後續分解了。在這裏我們就用標準的分詞器(StandardAnalyzer)
  4. 索引庫:要把文檔寫入到索引庫,並且根據分詞器進行分詞、建立索引,這得建索引庫吧,在lucene中對應的是Directory,它可以建立在內存中,也可以建立在硬盤中。
  5. 一切具備,只缺把文檔寫入到索引庫了,用什麼呢?當然是IndexWriter。

好了,這就是lucene創建索引的過程,下面看看代碼是怎樣表現的。

 

 

六、 代碼示例


Lucene在lucene-3.6.1-src/contrib/demo/src/java/org/apache/lucene/demo中提供了入門的示例代碼。 

  • IndexFiles.java是關於建立索引的示例。 
  • SearchFiles.java是關於進行檢索的示例。

1. 在文件系統中建立索引的代碼

 1 String indexPath = "/lucene/myindex"; 
 2 Directory dir = FSDirectory.open(new File(indexPath));  
 3 Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); 
 4 IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_36, analyzer); 
 5 iwc.setOpenMode(OpenMode.CREATE); //即創建新索引文件OpenMode.CREATE_OR_APPEND表示創建或追加到已有索引文件 
 6 IndexWriter writer = new IndexWriter(dir, iwc); 
 7 Document doc = new Document();  
 8 doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.ANALYZED));  
 9 doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index. ANALYZED));  
10 writer.addDocument(doc);  
11 writer.close()

 

 

2. 直接在內存中建立索引的代碼

 1 Directory dir = new RAMDirectory();  
 2 Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); 
 3 IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_36, analyzer); 
 4 iwc.setOpenMode(OpenMode.CREATE); //即創建新索引文件OpenMode.CREATE_OR_APPEND表示創建或追加到已有索引文件 
 5 IndexWriter writer = new IndexWriter(dir, iwc); 
 6 Document doc = new Document();  
 7 doc.add(new Field("title", "lucene introduction", Field.Store.YES, Field.Index.ANALYZED));  
 8 doc.add(new Field("content", "lucene works well", Field.Store.YES, Field.Index. ANALYZED));  
 9 writer.addDocument(doc);  
10 writer.close();

 

3. 對整個文本文件my.txt建立索引的代碼

 1  2 File file = new File(“/home/hanxb/my.txt”); 
 3 FileInputStream fis = new FileInputStream(file);
 4 Document doc = new Document();   
 5 Field pathField = new Field("path", file.getPath(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS); 
 6 pathField.setIndexOptions(IndexOptions.DOCS_ONLY); 
 7 doc.add(pathField);  
 8 NumericField modifiedField = new NumericField("modified");//索引key爲modified 
 9 modifiedField.setLongValue(file.lastModified());//文件的最後修改時間 
10 doc.add(modifiedField);  
11 doc.add(new Field("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));  
12 writer.addDocument(doc);//這裏爲創建新的索引文件 
13 //如果爲創建或追加索引文件, 則writer.updateDocument(new Term("path", file.getPath()), doc);  
14 fis.close(); 
15 writer.close()

 

4. 檢索“Cloud Computing”關鍵詞的代碼

 1 IndexReader reader = IndexReader.open(FSDirectory.open(new File(index))); 
 2 IndexSearcher searcher = new IndexSearcher(reader); 
 3 Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); 
 4 QueryParser parser = new QueryParser(Version.LUCENE_36, field, analyzer); 
 5 Query query = parser.parse("Cloud Computing"); //搜索關鍵詞“Cloud Computing” 
 6 searcher.search(query, null, 100); 
 7 TopDocs results = searcher.search(query, 10); //只取排名前10的搜索結果 
 8 ScoreDoc[] hits = results.scoreDocs; 
 9 Document doc = null; 
10 for (int i = start; i < end; i++) { 
11     doc = searcher.doc(hits[i].doc); 
12     String path = doc.get("path"); 
13     long modifiedtime = doc.get("modified"); 
14     String contents = doc.get("contents"); 
15 } 
16 searcher.close(); 
17 reader.clos

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章