1. 程式人生 > >5分鐘瞭解lucene

5分鐘瞭解lucene

本文通俗地介紹了Lucene全文檢索的內容及工作原理,以及索引的結構,旨在讓以前未了解過Lucene的讀者在能在短時間內對Lucene有簡單認知,未介紹具體程式碼,讀完本文可知道Lucene是什麼,有哪些具體應用,我們一直說的索引是什麼。

 

 

 

 

 Lucene介紹及應用

 

 

         Apache Lucene是當下最為流行的開源全文檢索工具包,基於JAVA語言編寫。

目前基於此工具包開源的搜尋引擎,成熟且廣為人知的有Solr和Elasticsearch。2010年後Lucene和Solr兩個專案由同一個Apache軟體基金會的開發團隊製作,所以通常我們看到的版本都是同步的。二者的區別是Lucene是工具包,而Solr是基於Lucene製作的企業級搜尋應用。另外,我們常用的Eclipse,幫助系統的搜尋功能也是基於Lucene實現的。

 

 

 Lucene的兩項工作

 

 

我們的生活物品中,漢語字典與全文索引是很相似的。我們拿拼音查字法舉例,首先我們通過拼音找到我們要查字的頁數,然後翻到該頁,閱讀這個字的詳細解釋。

在上面的例子中,我們提到了兩個要素:一個是字典,另一個是查字的過程。對應到Lucene的功能上,一個是我們要建立一個字典,這個過程叫做建立索引,另一個是根據搜尋詞基於索引進行查詢。

 

 

建立索引

 

1. 文件的準備(Document)

        文件就是指我們要去搜索的原文。

2. 分片語件(Tokenizer)

        將第一步的文件進行詞語切割,去除標點,去除無用詞,比如“是”,“的”等。常用的開源中文分片語件有MMSEG4J、IKAnalyzer等。切割後的詞語我們稱為詞元(Token)。

3. 語言處理(Linguistic Processor)

        將上一步的獲得的詞元進行處理,比如英文的大寫轉小寫,複數變單數,過去時分詞轉原形等。此時得到的結果,被稱作詞(Term)

4. 索引元件

        索引元件將上步得到的詞,生成索引和詞典,儲存到磁碟上。索引元件先將Term變成字典,然後對字典進行排序,排序後對相同的詞進行合併,形成倒排列表。每個詞在列表中儲存了對應的文件Id(Document Frequency)以及這個詞在這個文件中出現了幾次(Term Frequency)。

 

 

搜尋

 

1. 輸入查詢詞

2. 詞法分析及語言處理

        對輸入的詞進行拆分,關鍵字識別(AND,NOT)等。對拆分的詞元進行語言處理,與建立字典時語言處理的過程相同。由關鍵字與處理後的詞生成語法樹。

3. 搜尋索引,獲得符合語法樹的文件

        如A and B not C形成的語法樹,則會搜尋包含A B C的文件列表,然後用A和B的文件列表做交集,結果集與C做差集,得到的結果,就是符合搜尋條件的文件列表

4. 根據相關性,對搜尋結果排序

        通過向量空間模型的演算法,得到結果的相關性。比較簡單的實現描述如下:在建立索引的時候,我們得到了Document Frequency和Term Frequency,Term Frequency越高,說明文件的相關性越高;Document Frequency越高,說明相關性越弱。這個演算法可以自己進行實現。

5. 根據上面的排序結果,返回文件。

 

 

索引結構

 

 

        Lucene的索引結構是有層次結構的。我們以下圖為例

 

 

 

 

索引(Index)

 

如果拿資料庫做類比,索引類似於資料庫的表。

在Lucene中一個索引是放在一個資料夾中的。所以可以理解索引為整個資料夾的內容。

 

 

段(Segment)

 

        如果拿資料庫做類比,段類似於表的分割槽。

索引下面引入了Segment 的概念,一個索引下可以多個段。當flush或者commit時生成段檔案。截圖中有0,1兩個段。segments.gen和segments_5是段的元資料檔案,它們儲存了段的屬性資訊。其他的檔案對應的就是各段的檔案,稍後會詳細說明各檔案的用處。

索引的寫入是順序的,只能被追加,不能被修改。當索引要刪除時,在.del檔案中寫入對應的docId。查詢的時候會過濾到此docId。另外索引的修改,是對Document進行刪除後做的追加。這種設計保證了高吞吐量。

        分段的設計能保證查詢的高效,當段太大時,查詢會產生很大的IO消耗。段太小,則需要查詢的段太多。所以lucene對段進行了合併,另外刪除的資料也是在合併過程中過濾掉的。4.0之前的預設的合併策略為LogMergePolicy,這個策略會合並小於指定值的相鄰段,如果兩個相鄰段,一個大小為1G,一個大小為1k,則會重寫1G的檔案會佔用很大資源。4.0之後預設策略改為了TieredMergePolicy,這個策略會先按分段大小進行排序,對段進行刪除比計算,優先合併小的分段。當系統閒暇的時候,才對大分段進行合併。

 

 

 

文件(Document)

 

如果拿資料庫做類比,文件類似於資料的一行。

Document是索引的基本單位。一個段可以有多個Document

 

 

 

域(Field)

 

        如果拿資料庫做類比,域相當於表的欄位。

Doument裡可以有多個Field。Lucene提供多種不同型別的Field,例如StringField、TextField、LongFiled或NumericDocValuesField等。

 

 

詞(Term)

 

        Term是索引的最小單位。Term是由Field經過Analyzer(分詞)產生。

 

 

段的檔案說明

 

 

        第三小節詳細描述了段的設計和合並策略,以下詳細講解一些段檔案的內容。

        segments_N儲存了此索引包含多少個段,每個段包含多少篇文件。

*.fnm

        儲存了此段包含了多少個域,每個域的名稱及索引方式。

*.fdx,*.fdt

        儲存了此段包含的所有文件,每篇文件包含了多少域,每個域儲存了那些資訊。

*.tvx,*.tvd,*.tvf

儲存了此段包含多少文件,每篇文件包含了多少域,每個域包含了多少詞,每個詞的字串,位置等資訊。

*.tis,*.tii

        儲存了詞典(Term Dictionary),也即此段包含的所有的詞按字典順序的排序。

*.frq

        儲存了倒排表,也即包含每個詞的文件ID列表。

*.prx

儲存了倒排表中每個詞在包含此詞的文件中的位置

*.del

        前面講段的時候有提到,用來是儲存刪掉文件id的。