5、IndexWriter
索引這部分最後講的是IndexWriter。如果說前面提到的都是資料的結構,那麼IndexWriter就是業務的封裝。無論述Document,Field還是看不見的Segment,Term都是對資料存放區邏輯的抽象,IndexWriter封裝了操作的過程。
當然,這裡不會討論IndexWriter的每個細節,這裡主要介紹IndexWriter的常用法和實際使用中遇到的部署問題。
5.1 IndexWriter的常用方法
IndexWriter的用法很簡單,前文有例子。在《接觸Lucene.Net 》一文中代碼2.1.1就是最簡單的用法。可以看到IndexWriter的建構函式很重要,AddDocument方法也很重要,有這兩個方法,就可以建立索引了。其它的方法都是對建立索引的過程或者結果進行了最佳化,或者是提供了一些索引中或者索引後的資料。比如,常用的Optimize方法,就是對索引進行最佳化,使得搜尋能夠效率更高。還有一些常用的方法(按字母排序):
(1)、AddIndexes方法是合并不同部分索引的,這個方法很有用,比如,用5個線程在5個目錄下建立索引,然後用這個方法把5個索引合并為一個,這樣就能提高索引的效率;
(2)、Close方法是最後使用的方法,除了能夠去除對檔案的鎖定外,還能起到Flush方法的作用。這個方法非常重要,在IndexWriter執行個體建立後,無論出現什麼樣的問題,哪怕程式崩潰,都一定要顯式調用該方法。要不然索引會處於鎖定狀態,無法解除;
(3)、DeleteDocuments是用來刪除索引的,這裡只能指定Term刪除,使用價值不是太高;
(4)、Flush方法是把緩衝資料寫入的一個方法,在不想關閉索引但是要清空緩衝區的時候使用;
(5)、Optimize方法是最佳化索引的方法,如果索引資料很大,則調用這個方法會耗費很長時間。另外就是,如果索引檔案這個時候被讀取,並不能達到刪除廢棄檔案的目的。
(6)、SetMaxBufferedDocs方法是規定緩衝區能夠緩衝Document的個數,因為寫硬碟要比寫記憶體慢很多,這個值設定得越大,暫時儲存到記憶體的Document就會越多;
(7)、SetMaxFieldLength方法設定Field的最大長度;
(8)、UpdateDocument用來更新索引,但是實際上並不是真正的更新,而是先刪除,再添加,如果不進行最佳化,那麼至少會增加兩個檔案,一個記錄了增加的一個記錄了刪除的。
5.2 索引的部署
索引的部署根據索引的大小而趨向複雜,我認為至少是平方增長。複雜度增長的原因在於,索引大小的增長,將會引入更多需要考慮的因素。比如,索引的重建,索引最佳化時間,多索引部署等,而分布式部署基本上是目前最複雜的部署方案。
一般來說,應該一個索引儲存,只應該由一個IndexWriter來控制。一個儲存不應該超過2G,即使是2G,每次索引更新都需要10分鐘左右來最佳化索引。至於如何分配索引,要根據實際情況來決定,而且要考慮諸如程式崩潰等情況。
在Java版的搜尋引擎解決方案中有很多可以借鑒的地方,比如,對於資料索引,Compass的索引方式可以參考;對於抓取式的搜尋引擎,Nutch可以參考;分布式解決方案可以參考Hadoop。如何?像Compass一樣,添加、刪除、更新都能及時反映到索引當中,站內搜尋引擎一般都會面臨這樣的問題。Lucene.Net已經為我們提供了實現的方法,至於實現的邏輯需要你去思考。
6、索引小節
本篇文章是索引部分的完結篇。從第一篇到這裡第七篇,主要介紹了兩個東西,一個是Lucene.Net的邏輯儲存,另外一個就是如何操作邏輯儲存。在邏輯儲存上講得比較詳細,特別是關於權重部分,而操作則只簡單提一下。因為,邏輯儲存有助於理解Lucene.Net索引的流程,而操作則只是相當於CPU的指令,商務邏輯需要自己去實現。相信看了以上七篇文章,有助於對Lucene.Net索引的理解,當然,這裡只講了表面上的東西,更加深入地理解Lucene需要從更加底層的Directory入手。索引部分就暫時寫到這裡了,後面將進入搜尋問題的探討。