Lucene整理--索引的建立
看lucene主頁(http://lucene.apache.org/)上眼下lucene已經到4.9.0版本號了, 參考學習的書是依照2.1版本號解說的,寫的代碼樣例是用的3.0.2版本號的,版本號
的不同導致有些方法的使用差異,可是大體還是同樣的。
源碼用到的jar包(3.0.2版本號)下載地址
參考資料:
1、公司內部培訓資料
2、《Lucene搜索引擎開發權威經典》於天恩著.
Lucene使用挺簡單的,耐心看完都能學會,還有源碼。
一、創建索引的基本方式
全部開源搜索引擎的基本架構和原理都是類似的,Lucene也不例外,用它來建立搜索引擎也是要解決的四個基本問題:抓取數據、解析數據、創建索引和運行搜索。
1、理解創建索引的過程
參考書中對索引的創建有一個非常形象的比喻:
創建索引的過程能夠類比為寫文集。以下以文集的寫作為例進行解說,文集裏面有很多文章,每一篇文章包含標題、內容、作品名稱、寫作時間等信息。
我們採用下面的方式來寫這本文集:先寫文章,再將文章整合起來。
首先為每一篇文章加入標題、內容、寫作時間等信息,從而寫好一篇文章。
然後把每一篇文章加入到書裏面去,這樣文集就寫好了。
文集的結構例如以下圖所看到的:按從左到右的方向,是讀文集,即打開一本書,然後翻閱裏面的文章。按從右到左的方向是寫文集。
創建索引的步驟例如以下:
(1)、建立索引器IndexWriter。這相當於一本書的框架
(2)、建立文檔對象Document,這相當於一篇文章
(3)、建立信息字段對象Field,這相當於一篇文章中的不同信息(標題、正文等)。
(4)、將Field加入到Document裏面。
(5)、將Document加入到IndexWriter裏面。
(6)、關閉索引器IndexWriter。
例如以下圖所看到的是一個索引的結構,按從左到右是讀索引(即搜索)。按從右到左是創建索引:
依照上圖所看到的的結構,創建索引有三個主要的步驟:
(1)、創建Field,將文章的不同信息包裝起來
(2)、將多個Field組織到一個Document裏面。這樣完畢了對一篇文章的包裝。
(3)、將多個Document組織到一個IndexWriter裏面,也就是將多個文章組裝起來,終於形成索引
以下的三個小節就依照創建索引的基本步驟來解說創建索引的詳細方法。
2、創建Field
創建Field的方法有很多。以下是最經常使用的方法。
Field field=new Field(Field名稱,Field內容,存儲方式,索引方式);
這四個參數的含義例如以下:
(1)、Field名稱就是為Field起的名字。類似於數據表的字段名稱。
(2)、Field內容就是該Field的內容,類似數據庫表的字段內容。
(3)、存儲方式包含三種:不存儲(Field.Store.NO)、全然存儲(Field.Store.YES)和壓縮存儲(Field.Store.COMPRESS)。
通常。假設不操心索引太大的話。能夠都使用全然存儲的方式。
可是。出於對性能的考慮。索引文件的內容是越小越好。因此。假設Field的內容非常少就採用全然存儲(如標
題),假設Field的內容非常多就採用不存儲或壓縮存儲的方式,如正文。
(4)、索引的方式包含四種:
不索引(Field.Index.NO)、索引但不分析(Field.Index.NO_NORMS)、索引但不分詞(Field.Index.UN_TOKENIZED)、分詞並索引(Field.Index.TOKENIZED)。
3、創建Document
創建Document方法例如以下:
Document doc=new Document();
這種方法用來創建一個不含有不論什麽Field的空Document。
假設想把Field加入到Document裏面,僅僅須要add方法。比如doc.add(field);
反復的使用就能夠將多個Field增加到一個Document裏面。
4、創建IndexWriter
創建IndexWriter方式也不少,拿出一個經常使用的:
<span style="font-family:SimSun;font-size:12px;"><span style="font-family:SimSun;font-size:12px;"> File indexDir = new File("E:\\Index"); Directory dir = new SimpleFSDirectory(indexDir); Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); IndexWriter indexWriter = new IndexWriter(dir, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);</span></span>
關於幾個參數的介紹:
(1)、Directory (文件夾類型) 該類是抽象類
它的直接子類在不同版本號中還是有差別的,我們直說3.0.2版本號,它的子類包含FSDirectory、RAMDirectory、FileSwitchDirectory、CompoundFileReader,兩個子類代表著不同的兩種文件夾類型
FSDirectory:文件系統中的一個路徑,會直接將索引寫入到磁盤上
RAMDirectory:內存中的一個區域,虛擬機退出後內容會隨之消失,所以須要將RAMDirectory中的內容轉到FSDirectory。
FileSwitchDirectory:一個是用於能夠同一時候在兩個不同的文件夾中讀取文件的FileSwitchDirectory,這是個代理類。
CompoundFileReader:是用戶讀取復合文件的CompoundFileReader。僅僅能讀取擴展名為cfs的文件。(寫擴展名為cfs的文件用CompoundFileWriter)CompoundFileReader僅在SegmentReader中被引用。
當中FSDirectory又分為3類:
A、windows下的SimpleFSDirectory
B、linux支持NIO的NIOFSDirectory
C、另一個是內存Map文件夾MMapDirectory
(2)、Analyzer(分析器) 抽象類
負責對各種輸入的數據源進行分析,包含過濾和分詞等多種功能。
分析器是用來做詞法分析的,包含英文分析器和中文分析器等。要依據所要建立的索引的文件情況選擇合適的分析器。經常使用的有StandardAnalyzer(標準分析器)、CJKAnalyzer(二分法分詞
器)、ChineseAnalyzer(中文分析器)等。
能夠依據自己的須要去編輯分析器,從而處理不同 的語言文字(當然,我不會)。
IndexWriter創建完之後能夠用addDocument()的方法將document對象放置到IndexWriter中:writer.addDocument(doc);
能夠放置多個。
終於要調用close()方法關閉索引器,比如writer.close();
到此,創建索引的步驟就介紹完了,以下我們就該看實例了:
二、創建一個簡單索引實例:
<span style="font-family:SimSun;font-size:12px;">import java.io.File; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.store.Directory; import org.apache.lucene.store.SimpleFSDirectory; import org.apache.lucene.util.Version; public class LuceneMainProcess { public static void main(String[] args) { createLuceneIndex(); } public static void createLuceneIndex() { try { File indexDir = new File("E:\\Index"); Directory dir = new SimpleFSDirectory(indexDir); Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30); //IndexWriter為某個Document建立索引時所取到的Field內的最大詞條數目,該屬性的初始值為10000 IndexWriter indexWriter = new IndexWriter(dir, analyzer, true, IndexWriter.MaxFieldLength.LIMITED); // 創建8個文檔 Document doc1 = new Document(); Document doc2 = new Document(); Document doc3 = new Document(); Document doc4 = new Document(); Document doc5 = new Document(); Document doc6 = new Document(); Document doc7 = new Document(); Document doc8 = new Document(); Field f1 = new Field("bookname", "鋼鐵是如何煉成的", Field.Store.YES, Field.Index.ANALYZED); Field f2 = new Field("bookname", "英雄兒女", Field.Store.YES, Field.Index.ANALYZED); Field f3 = new Field("bookname", "籬笆女人和狗", Field.Store.YES, Field.Index.ANALYZED); Field f4 = new Field("bookname", "女人是水做的", Field.Store.YES, Field.Index.ANALYZED); Field f5 = new Field("bookname", "我的兄弟和女兒", Field.Store.YES, Field.Index.ANALYZED); Field f6 = new Field("bookname", "白毛女", Field.Store.YES, Field.Index.ANALYZED); Field f7 = new Field("bookname", "鋼的世界", Field.Store.YES, Field.Index.ANALYZED); Field f8 = new Field("bookname", "鋼鐵戰士", Field.Store.YES, Field.Index.ANALYZED); doc1.add(f1); doc2.add(f2); doc3.add(f3); doc4.add(f4); doc5.add(f5); doc6.add(f6); doc7.add(f7); doc8.add(f8); indexWriter.addDocument(doc1); indexWriter.addDocument(doc2); indexWriter.addDocument(doc3); indexWriter.addDocument(doc4); indexWriter.addDocument(doc5); indexWriter.addDocument(doc6); indexWriter.addDocument(doc7); indexWriter.addDocument(doc8); indexWriter.optimize();//對索引進行優化,保證檢索時的速度,可是須要消耗內存和磁盤空間,耗時耗力,須要的時候再優化(而非隨意時刻) indexWriter.close();//關閉索引器,否則會導致索引的數據滯留在緩存中未寫入磁盤,有可能連文件夾的鎖也沒有去除 } catch (Exception e) { e.printStackTrace(); } } } </span>
運行之後我們發現E盤下出現了一個index文件夾,這就是我們創建的索引文件。
到此,索引文件也就是創建完成了。
明天接著往下整理索引的讀取,到時候我們就能夠更直觀的推斷上面創建的索引是否成功。
Lucene整理--索引的建立