Lucene
簡介
編輯Lucene最初是由Doug Cutting所撰寫的,是一位資深全文索引/檢索專家,曾經是V-Twin搜尋引擎的主要開發者,後來在Excite擔任高級系統架構設計師,目前從事於一些INTERNET底層架構的研究。他貢獻出Lucene的目標是為各種中小型應用程式加入全文檢索功能。 Lucene提供了一個簡單卻強大的應用程式介面,能夠做全文索引和搜尋,在java裏Lucene是一個成熟的免費開放原始碼工具;就其本身而論,Lucene是現在並且是這幾年,最受歡迎的免費java資訊檢索程式庫。人們經常提到資訊檢索程式庫,就像是搜尋引擎,但是不應該將資訊檢索程式庫與網搜尋引擎相混淆。
如何使用Lucene
編輯Step1:Lucene下載完後將裏面的lucene-core-{version}.jar 和lucene-demos-{version}.jar 和 queryparser/lucene-queryparser-{version}.jar 放到
C:\Program Files\Java\jdk1.5.0_11\jre\lib\ext的目錄下
Step2:將上面的3個.jar的檔案路徑加入到CLASSPATH裏完成上面步驟後就可以在Command line下使用Lucene建立Index以及Search。
建立Index:
在Command line下輸入java org.apache.lucene.demo.IndexFiles {full-path-to-lucene}/src 即可建立Index。
Search:
在建立完Index之後接着輸入java org.apache.lucene.demo.SearchFiles之後會出現Query:字樣接着就可以開始Search。
linux環境, lucene-6.3.0例子:
- 取得 lucene-6.3.0.tgz。
- 假設id為boy, cd /home/boy;mkdir lucene
- cd /home/boy; tar zxf lucene-6.3.0.tgz
- export CLASSPATH=/home/boy/lucene-6.3.0/core/lucene-core-6.3.0.jar:/home/boy/lucene-6.3.0/demo/lucene-demo-6.3.0.jar:/home/boy/lucene-6.3.0/queryparser/lucene-queryparser-6.3.0.jar
- cd /home/boy;java org.apache.lucene.demo.IndexFiles -docs /home/boy/lucene-6.3.0 將會讀取/home/boy/lucene-6.3.0檔案,建立index在目錄 /home/boy/index。
- java org.apache.lucene.demo.SearchFiles之後會出現Query:字樣接着就可以開始Search。
Lucene分詞原理
編輯假若有以下2篇文章:
文章1的內容是:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的內容是:He once lived in Shanghai.
Lucene是用關鍵詞索引和搜尋的,所以我們要先取得上面兩篇文章的關鍵詞,步驟如下:
Step1:先找出文章中所有的單字,即分詞,因為英文單字是用空格分隔,所以比較好處理,若是中文分詞需用到特殊的分詞處理。
Step2:把文章中沒有意義的單字濾掉,EX:"in","once","too"等等,在中文中就是,"的","是"等等。
Step3:使用者若查詢"He"時要能把"he","HE"的文章也找出來,所以所有單字需要統一大小寫。
Step4:使用者若查詢"live"時,也要將"lives","lived"的文章找出來所以需要把"lives","lived"還原成"live"。
Step5:文章中的標點符號也可以過濾掉。
以上步驟在Lucene中是由Analyzer來完成的。
文章經過處理後:
文章1的所有關鍵詞為:[tom] [live] [guangzhou] [i] [live] [guangzhou]
文章2的所有關鍵詞為:[he] [live] [shanghai]
有了所有的關鍵詞後,我們就可以開始建立倒排索引了。
上面處理過的文章所對應的關係是:"文章編號","文章中所有的關鍵詞"。
若使用一般的索引結構會如下表所示:
文章編號 | 出現的關鍵詞 | 出現次數 |
---|---|---|
1 | guangzhou,i,live,tom | 1,1,1,1 |
2 | he,live,shanghai | 1,1,1 |
從中可以看出一般索引結構是以文章為標準建立索引結構,也就是說他紀錄的是一篇文章中所有的關鍵詞出現的情況,EX:文章2中he,live,shanghai均出現一次,然而使用者進行搜尋時,都是輸入關鍵字進行搜尋,若用這種索引結構,在查某依關鍵字時往往需要遍及所有的索引,當索引量非常大時,效率會成為一個很大的問題。
而倒排索引會把這關係變成:"關鍵詞","出現關鍵詞的所有文章編號"。
所以索引結構如下表所示:
關鍵詞 | 出現關鍵詞的所有文章編號 |
---|---|
guangzhou | 1 |
he | 2 |
i | 1 |
live | 1,2 |
shanghai | 2 |
tom | 1 |
通常只知道以上資訊是不夠的,我們還需要知道關鍵詞在文章中出現的次數以及位置。
關鍵詞位置有兩種:
符號位置:即紀錄該關鍵詞是在文章中第幾個符號。
關鍵詞位置:即記錄該關鍵詞是在文章中的第幾個關鍵詞。(Lucene所用的)
所以上面的資料加入"出現頻率"和"出現位置"的訊息後,索引結構就如下表所示:
關鍵詞 | 出現關鍵詞的所有文章編號[出現頻率] | 出現位置 |
---|---|---|
guangzhou | 1[2] | 3,6 |
he | 2[1] | 1 |
i | 1[1] | 4 |
live | 1[2],2[1] | 2,5,2 |
shanghai | 2[1] | 3 |
tom | 1[1] | 1 |
以live這行來說明索引結構:live在文章1中出現了2次,在文章2中出現了1次,出現的位置為"2,5,2",也就是說live在文章1中出現了2次,位置分別是"2,5";live在文章2中出現了一次,位置是"2"。
上面就是Lucene索引結構中最核心的部份。我們可以看出關鍵詞是依照符號順序排列的,因此Lucene可以利用二元搜尋法來定位關鍵詞。
實際上Lucene將上面的"關鍵詞","文章編號[出現頻率]","出現位置"分成(辭典文件)Term Dictionary,(頻率文件)frequencies,(位置文件)positions保存。
其中Term Dictionary不只存有每個關鍵詞,還保留了frequencies和positions的指針,透過指針可以找到該關鍵詞的頻率訊息和位置訊息。
Lucene也使用了field的概念,field是用於表達訊息的所在位置(EX:標題中,文章中,url中),在建立索引時field的訊息也被記錄在Term Dictionary中,每一個關鍵詞都有一個field訊息(因為每一個關鍵詞一定屬於一個或多個)。
下面我們將說明為什麼要建立索引(Index):
假設我們查詢"live",Lucene會用二元搜尋法對Term Dictionary做關鍵詞的尋找,找到該關鍵詞後,透過指向frequencies的指針讀出所有的文章編號,然後將找到的文章輸出給使用者。Term Dictionary通常都很小,所以整個過程的時間是毫秒級的。