本文主要討論Lucene的系統結構,希望對其結構的初步分析,更深入的了解Lucene的運作機制,從而實(shí)現對Lucene的功能擴展。
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->1. <!--[endif]-->Lucene的包結構
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !vml]-->
<!--[endif]-->
如上圖所示,Lucene源碼中共包括7個(gè)子包,每個(gè)包完成特定的功能:
<!--[if !supportEmptyParas]--> <!--[endif]-->
Lucene包結構功能表
包名
功能
org.apache.lucene.analysis
語(yǔ)言分析器,主要用于的切詞,支持中文主要是擴展此類(lèi)
org.apache.lucene.document
索引存儲時(shí)的文檔結構管理,類(lèi)似于關(guān)系型數據庫的表結構
org.apache.lucene.index
索引管理,包括索引建立、刪除等
org.apache.lucene.queryParser
查詢(xún)分析器,實(shí)現查詢(xún)關(guān)鍵詞間的運算,如與、或、非等
org.apache.lucene.search
檢索管理,根據查詢(xún)條件,檢索得到結果
org.apache.lucene.store
數據存儲管理,主要包括一些底層的I/O操作
org.apache.lucene.util
一些公用類(lèi)
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->2. <!--[endif]-->Lucene的主要邏輯圖
<!--[if !supportEmptyParas]--> <!--[endif]-->
Lucene功能強大,但從根本上說(shuō),主要包括兩塊:一是文本內容經(jīng)切詞后索引入庫;二是根據查詢(xún)條件返回結果。
以下是上述兩大功能的邏輯圖:
<!--[if !supportEmptyParas]--> <!--[endif]-->
STORAGE
(存儲器)
ACCESS INDEX
(訪(fǎng)問(wèn)索引)
SERACHER
(查詢(xún)器)
ANALYZER
(語(yǔ)言分析器)
QUERY PARSER
(查詢(xún)分析器)
DOCUMENT
(文檔結構)
SEARCHER
(查詢(xún))
INDEXER
(入庫)
FS
BDD
RAM
Lucene功能邏輯圖
<!--[if !vml]-->
<!--[endif]--><!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
查詢(xún)邏輯
<!--[if !supportEmptyParas]--> <!--[endif]-->
按先后順序,查詢(xún)邏輯可分為如下幾步:
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->1. <!--[endif]-->查詢(xún)者輸入查詢(xún)條件
條件之間可以通過(guò)特定運算符進(jìn)行運算,比如查詢(xún)希望查詢(xún)到與“中國”和“北京”相關(guān)的記錄,但不希望結果中包括“海淀區中關(guān)村”,于是輸入條件為“中國+北京-海淀區中關(guān)村”;
<!--[if !supportLists]-->2. <!--[endif]-->查詢(xún)條件被傳達到查詢(xún)分析器中,分析器將將對“中國+北京-海淀區中關(guān)村”進(jìn)行分析,首先分析器解析字符串的連接符,即這里的加號和減號,然后對每個(gè)詞進(jìn)行切詞,一般最小的詞元是兩個(gè)漢字,則中國和北京兩個(gè)詞不必再切分,但對海淀區中關(guān)村需要切分,假設根據切詞算法,把該詞切分為“海淀區”和“中關(guān)村”兩部分,則最后得到的查詢(xún)條件可以表示為:“中國” AND “北京” AND NOT(“海淀區” AND “中關(guān)村”)。
<!--[if !supportLists]-->3. <!--[endif]-->查詢(xún)器根據這個(gè)條件遍歷索引樹(shù),得到查詢(xún)結果,并返回結果集,返回的結果集類(lèi)似于JDBC中的ResultSet。
<!--[if !supportLists]-->4. <!--[endif]-->將返回的結果集顯示在查詢(xún)結果頁(yè)面,當點(diǎn)擊某一條內容時(shí),可以鏈接到原始網(wǎng)頁(yè),也可以打開(kāi)全文檢索庫中存儲的網(wǎng)頁(yè)內容。
<!--[if !supportEmptyParas]--> <!--[endif]-->
這就是查詢(xún)的邏輯過(guò)程,需要說(shuō)明的是,Lucene默認只支持英文,為了便于說(shuō)明問(wèn)題,以上查詢(xún)過(guò)程采用中文舉例,事實(shí)上,當Lucene被擴充支持中文后就是這么一個(gè)查詢(xún)過(guò)程。
<!--[if !supportEmptyParas]--> <!--[endif]-->
入庫邏輯
<!--[if !supportEmptyParas]--> <!--[endif]-->
入庫將把內容加載到全文檢索庫中,按順序,入庫邏輯包括如下過(guò)程:
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->1. <!--[endif]-->入庫者定義到庫中文檔的結構,比如需要把網(wǎng)站內容加載到全文檢索庫,讓用戶(hù)通過(guò)“站內檢索”搜索到相關(guān)的網(wǎng)頁(yè)內容。入庫文檔結構與關(guān)系型數據庫中的表結構類(lèi)似,每個(gè)入庫的文檔由多個(gè)字段構成,假設這里需要入庫的網(wǎng)站內容包括如下字段:文章標題、作者、發(fā)布時(shí)間、原文鏈接、正文內容(一般作為網(wǎng)頁(yè)快照)。
<!--[if !supportLists]-->2. <!--[endif]-->包含N個(gè)字段的文檔(DOCUMENT)在真正入庫前需要經(jīng)過(guò)切詞(或分詞)索引,切詞的規則由語(yǔ)言分析器(ANALYZER)完成。
<!--[if !supportLists]-->3. <!--[endif]-->切分后的“單詞”被注冊到索引樹(shù)上,供查詢(xún)時(shí)用,另外也需要也其它不需要索引的內容入庫,所有這些是文件操作均由STORAGE完成。
<!--[if !supportEmptyParas]--> <!--[endif]-->
以上就是記錄加載流程,索引樹(shù)是一種比較復雜的數據存儲結構,將在后續章節陸續介紹,這里就不贅述了,需要說(shuō)明的一點(diǎn)是,Lucene的索引樹(shù)結構非常優(yōu)秀,是Lucene的一大特色。
<!--[if !supportEmptyParas]--> <!--[endif]-->
接下來(lái)將對Lucene的各個(gè)子包的結構進(jìn)行討論。
<!--[if !supportLists]-->3. <!--[endif]-->語(yǔ)言分析包org.apache.lucene.analysis
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
Analyzer是一個(gè)抽象類(lèi),司職對文本內容的切分詞規則。
<!--[if !supportEmptyParas]--> <!--[endif]-->
切分后返回一個(gè)TokenStream,TokenStream中有一個(gè)非常重要方法next(),即取到下一個(gè)詞。簡(jiǎn)單點(diǎn)說(shuō),通過(guò)切詞規則,把一篇文章從頭到尾分成一個(gè)個(gè)的詞,這就是org.apache.lucene.analysis的工作。
<!--[if !supportEmptyParas]--> <!--[endif]-->
對英文而言,其分詞規則很簡(jiǎn)單,因為每個(gè)單詞間都有一個(gè)空格,按空格取單詞即可,當然為了提高英文檢索的準確度,也可以把一些短語(yǔ)作為一個(gè)整體,其間不切分,這就需要一個(gè)詞庫,對德文、俄文也是類(lèi)似,稍有不同。
<!--[if !supportEmptyParas]--> <!--[endif]-->
對中文而言,文字之間都是相連的,沒(méi)有空格,但我們同樣可以把字切分,即把每個(gè)漢字作為一個(gè)詞切分,這就是所謂的“切字”,但切字方式方式的索引沒(méi)有意義,準確率太低,要想提高準確度一般都是切詞,這就需要一個(gè)詞庫,詞庫越大準確度將越高,但入庫效率越低。
<!--[if !supportEmptyParas]--> <!--[endif]-->
若要支持中文切詞,則需要擴展Analyzer類(lèi),根據詞庫中的詞把文章切分。
<!--[if !supportEmptyParas]--> <!--[endif]-->
簡(jiǎn)單點(diǎn)說(shuō),org.apache.lucene.analysis就是完成將文章切分詞的任務(wù)。
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->4. <!--[endif]-->文檔結構包org.apache.lucene.document
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
document包相對而言比較簡(jiǎn)單,該包下面就3個(gè)類(lèi),Document相對于關(guān)系型數據庫的記錄對象,主要負責字段的管理,字段分兩種,一是Field,即文本型字段,另一個(gè)是日期型字段DateField。這個(gè)包中關(guān)鍵需要理解的是Field中字段存儲方式的不同,這在上一篇中已列表提到,下面我們可以參見(jiàn)一下其詳細的類(lèi)圖:
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->5. <!--[endif]-->索引管理包org.apache.lucene.index
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
索引包是整個(gè)系統核心,全文檢索的的根本就為每個(gè)切出來(lái)的詞建索引,查詢(xún)時(shí)就只需要遍歷索引,而不需要去正文中遍歷,從而極大的提高檢索效率,索引建設的質(zhì)量關(guān)鍵整個(gè)系統的質(zhì)量。Lucene的索引樹(shù)是非常優(yōu)質(zhì)高效的,具體的索引樹(shù)細節,將在后續章節中重要探討。
<!--[if !supportEmptyParas]--> <!--[endif]-->
在這個(gè)包中,主要學(xué)習IndexWriter和IndexReader這個(gè)類(lèi)。
<!--[if !supportEmptyParas]--> <!--[endif]-->
通過(guò)上一篇的初步應用可知,全文檢索庫的初始化和記錄加載均需要通過(guò)該類(lèi)來(lái)完成。
<!--[if !supportEmptyParas]--> <!--[endif]-->
初始化全文庫的語(yǔ)句為:
IndexWriter indexWriter = new IndexWriter(“全文庫的目錄位置”,new StandardAnalyzer(),true);
<!--[if !supportEmptyParas]--> <!--[endif]-->
記錄加載的語(yǔ)句為:indexWriter.addDocument(doc);
<!--[if !supportEmptyParas]--> <!--[endif]-->
IndexWriter主要用于寫(xiě)庫,當需要讀取庫內容時(shí),就需要用到IndexReader這個(gè)類(lèi)了。
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->6. <!--[endif]-->查詢(xún)分析包org.apache.lucene.queryParser和檢索包org.apache.lucene.search
<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
通過(guò)查詢(xún)分析器(queryParser)解析后,將返回一個(gè)查詢(xún)對象(query),根據查詢(xún)對象就可進(jìn)行檢索了。上圖描述了query對象的生成,下圖描述了查詢(xún)結果集(Hits)的生成。
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->7. <!--[endif]-->存儲包org.apache.lucene.store
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
一些底層的文件I/O操作。
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->8. <!--[endif]-->工具包org.apache.lucene.util
<!--[if !vml]-->
<!--[endif]-->
<!--[if !supportEmptyParas]--> <!--[endif]-->
該包中包括4個(gè)工具類(lèi)。
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->9. <!--[endif]-->總結
<!--[if !supportEmptyParas]--> <!--[endif]-->
通過(guò)對Lucene源碼包的分析,我們可以初步認識到Lucene的核心類(lèi)包主要有3個(gè):
<!--[if !supportEmptyParas]--> <!--[endif]-->
<!--[if !supportLists]-->l <!--[endif]-->org.apache.lucene.analysis
<!--[if !supportLists]-->l <!--[endif]-->org.apache.lucene.index
<!--[if !supportLists]-->l <!--[endif]-->org.apache.lucene.search
<!--[if !supportEmptyParas]--> <!--[endif]-->
其中org.apache.lucene.analysis 主要用于切分詞,切分詞的工作由Analyzer的擴展類(lèi)來(lái)實(shí)現,Lucene自帶了StandardAnalyzer類(lèi),我們可以參照該寫(xiě)出自己的切詞分析器類(lèi),如中文分析器等。
<!--[if !supportEmptyParas]--> <!--[endif]-->
org.apache.lucene.index主要提供庫的讀寫(xiě)接口,通過(guò)該包可以創(chuàng )建庫、添加刪除記錄及讀取記錄等。
<!--[if !supportEmptyParas]--> <!--[endif]-->
org.apache.lucene.search主要提供了檢索接口,通過(guò)該包,我們可以輸入條件,得到查詢(xún)結果集,與org.apache.lucene.queryParser包配合還可以自定義的查詢(xún)規則,像google一樣支持查詢(xún)條件間的與、或、非、屬于等復合查詢(xún)。
本文引用通告地址(TrackBack Ping URL)為:
http://blog.ccw.com.cn/trackback.jsp?postID=8091