?»??»?MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_01C5A13C.E9AE6F80" ¦¹¤å¥ó¬O¡u³æ¤@Àɮ׺ô­¶¡v¡A¥çºÙ¬°¡uºô­¶«Ê¦sÀɮסv¡C­Y¬Ý¨ì¦¹°T®§¡Aªí¥Ü±zªºÂsÄý¾¹©Î½s¿è¾¹¤£¤ä´©¡uºô­¶«Ê¦sÀɮסv¡C½Ð¤U¸ü¤ä´©¡uºô­¶«Ê¦s¡vªºÂsÄý¾¹¡A¨Ò¦p Microsoft Internet Explorer¡C ------=_NextPart_01C5A13C.E9AE6F80 Content-Location: file:///C:/9FC05CDD/file4029.htm Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset="us-ascii" 在應用中加入全文= 298;索功能

 

在應用中加入全文= 7298;索功能
    ——
基於Java的全文索引引擎= Lucene= 簡介

http://www.chedong.com/= tech/lucene.html

 

作者: 車東 Email: chedongATbigfoot.com/chedongATchedong.com

寫於:2002/08 <= /span>最後更新:= ; 03/16/2005 16:27:52
Feed Back >&g= t; (Read this befor= e you ask question)
3D"Creative

版權聲明:= ;可以任意轉載,轉載&#= 26178;請務必以超鏈結形ó= 35;標明文章原始出處和= 作者資訊及本聲明
http://www.chedong.c= om/tech/lucene.html

關鍵字:= Lucene java full-text search engine Chinese word segment

內容摘要:= ;

Lucene是一個基於Java的全文索引= ;工具包。

= 1. = 2522;於Java= 0340;全文索引引擎<= span style=3D'mso-bidi-font-size:12.0pt'>Lucene= 1777;介:關於作者和= Lucene= 0340;歷史

= 2. = 0840;文檢索的實現:= Luene= 0840;文索引和資料庫索ং= 1;的比較

= 3. = 0013;文切分詞機制簡介ᦂ= 6;基於詞= 4235;和自動切分詞演算ૢ= 1;的比較

= 4. = 0855;體的安裝和使用簡ߡ= 1;:系統結構介紹和演&= #31034;

= 5. Hacking Lucene= 5306;簡化的查詢分析器ᦁ= 2;刪除的實現,定制的&= #25490;序,應用介面的擴= 637;

= 6. = 4478;Lucene= 5105;們還可以學到什麼

基於Java的全文索引= ;/<= /u>檢索引擎= ——Lucene

Lucene不是一個完整į= 40;全文索引應用,而是= 一個用Java寫的全文索引ó= 41;擎工具包,它可以方= 便的嵌入到各種應用= 0013;實現針對應用的全ਧ= 1;索引/<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>檢索功能。= ;

Lucene的作者:Lucene的貢獻者Doug Cutting是一位元資= ;深全文索引/<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>檢索專家,= ;曾經是V-Twin搜索引擎= (AppleCopland作業系統的= ;成就之)的主要開發者ʌ= 92;後在Excite擔任高級系= ;統架構設計師,目前&#= 24478;事於一些INTERNET<= /span>底層架構的= ;研究。他貢獻出的Lucene的目標是為各ĸ= 78;中小型應用程式加入= 全文檢索功能。

Lucene的發展歷程:Ą= 89;先發佈在作者自己的= www.lucene.com,後來發佈= ;在SourceForge2001年年底成為APACHE基金會jakarta個&#= 23376;項目:http://jakarta.apache.org/luc= ene/

已經有很多= ;Java專案都使用= ;了Lucene作為其後&= #33274;的全文索引引擎ʌ= 92;比較著名的有:

= ·    JiveWEB論&= #22727;系統;

= ·    Eyebrows:郵件列表HTML歸檔/流&= #35261;/查詢系統,本文的ߒ= 7;要參考文檔TheLucene search engine: Powerful, flex= ible, and free作者就是EyeBrows<= /span>系統的主要開į= 32;者之一,而EyeBrows<= /span>已經成為目前APACHE項目的主要郵Ê= 14;列表歸檔系統。

= ·    <= b>Cocoon:基於XML的<= /span>web發佈框架,全文檢ಃ= 4;部分使用了Lucene

·= ;    Eclipse:基於Java的開放開發平,幫助部分௚= 0;全文索引使用了Lucene

對於中文用= ;戶來說,最關心的問&#= 38988;是其是否支持中文į= 40;全文檢索。但通過後= 面對於Lucene的結構的介紹ʌ= 92;你會瞭解到由於Lucene良好架構設計ʌ= 92;對中文的支援只需對= 其語言詞法分析介面= 6914;行擴展就能實現對ߑ= 3;文檢索的支持。

全文檢索的= ;實現機制

LuceneAPI介面設計的比Ů= 11;通用,輸入輸出結構= 都很像資料庫的表=3D=3D>= ;記錄=3D=3D>欄位,所以= ;很多傳統的應用的檔&#= 12289;資料庫等都可以比Ů= 11;方便的映射到Lucene的存儲結構/<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>介面中。總= ;體上看:可以先把Lucene當成一個支援Ð= 40;文索引的資料庫系統=

比&= #36611;一下Lucene和資料庫:

Lucene

資料庫

索引資料源:doc(field1,field2...) doc(field1,field2...)
       &nbs= p;          \  indexer /
       &nbs= p;         _____________
       &nbs= p;        | Lucene Index|
       &nbs= p;        --------------
       &nbs= p;         / searcher \
 
結果$= 664;出:Hits(doc(field1,field2) doc(field1...))

 索= 引資料源:record(= field1,field2...) record(field1..)
       &nbs= p;      \  SQL: insert/
       &nbs= p;       _____________
       &nbs= p;      | DB  Index   |
       &nbs= p;       -------------
       &nbs= p;      / SQL: select \
結果輸出:results(record(field1,field= 2..) record(field1...))

Document:= ;一個需要進行索引的單= ;元
一個Document由= ;多個欄位組成

Record:= ;記錄,包含多個欄位

Field:= ;欄位

Field:= ;欄位

Hits:= ;查詢結果集,由匹配&#= 30340;Document組= ;成

RecordSet:查詢結果集,由= 810;個Record組= ;成

全文檢索= like "%keyword%"

通常比較厚= ;的書籍後面常常附關&#= 37749;字索引表比如:北京ᦂ= 6;12, 34頁,上海:= ;3,77= 230;,它能夠幫= ;助讀者比較快地找到&#= 30456;關內容的頁碼。而Ũ= 39;料庫索引能夠大大提= 高查詢的速度原理也= 6159;一樣,想像一下通๮= 2;書後面的索引查找的&= #36895;度要比一頁一頁地 = 763;內容高多少而索引之所= ;以效率高,另外一個&#= 21407;因是它是排好序的對= 6044;檢索系統來說核心਷= 9;一個排序問題

由於資料庫= ;索引不是為全文索引&#= 35373;計的,因此,使用like "%keyword%"時,資料庫索引是ߎ= 1;起作用的,在使用= like查詢時,搜= ;索過程又變成類似於&#= 19968;頁頁翻書的遍過程了,所ߣ= 7;對於含有模糊查詢的&= #36039;料庫服務來說,LIKE對性能的危= ;害是極大的。如果是&#= 38656;要對多個關鍵字進Ŝ= 92;模糊匹配:like"= ;%keyword1%" and like "%keyword2%" ...其效率也就可ø= 19;而知了。

所以建立一= ;個高效檢索系統的關&#= 37749;是建立一個類似於ķ= 85;技索引一樣的反向索= 引機制,將資料源(= 7604;如多篇文章)排序༳= 8;序存儲的同時,有另&= #22806;一個排好序的關鍵ढ= 3;列表,用於存儲關鍵&= #23383;=3D=3D>= ;文章映射關= ;係,利用這樣的映射&#= 38364;係索引:[<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>關鍵字=3D=3D>= ;出現關鍵字= ;的文章編號,出現次&#= 25976;甚至包括位ಾ= 2;:起始偏移量,結束&= #20559;移量,出現頻率]<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>,檢索過程= ;就是把模糊查詢變成= ;多個可以利用索引的&#= 31934;確查詢的邏輯組合į= 40;過程。從而大大提'= 640;了多關鍵字查詢的效= ;率,所以,全文檢索&#= 21839;題歸結到最後是一Ì= 91;排序問題。

由此可以看= ;出模糊查詢相對資料&#= 24235;的精確查詢是一個ƃ= 50;常不確定的問題,這= 也是大部分資料庫對= 0840;文檢索支援有限的࡜= 7;因。Lucene核心的特徵= ;是通過特殊的索引結&#= 27083;實現了傳統資料庫Ç= 81;擅長的全文索引機制= ,並提供了擴展介面= 5292;以方便針對不同應ஷ= 2;的定制。

可&= #20197;通過一下表格對比= 968;下資料庫的模糊查詢= ;:

 

Lucene全文索引引擎

資料庫

索引

將資料源中的資料%= 117;通過全文索引一一建= ;立反向索引

對於LIKE查詢來說,資料傳 = 113;的索引是根本用不上= ;的。資料需要逐便利記錄進"= 892;GREP式的模糊匹= ;配,比有索引的搜索&#= 36895;度要有多個數量級į= 40;下降。

匹配效果

通過詞元(term)進= ;行匹配,通過語言分&#= 26512;介面的實現,可以ë= 26;現對中文等非英語的= 支持。

使用:like "%net%" 會把netherlands也匹配出來,
多個關鍵é= 83;的模糊匹配:使用<= span lang=3DEN-US style=3D'font-family:"Trebuchet MS";mso-bidi-font-family:PMi= ngLiU; color:#333333;mso-font-kerning:0pt'>like "%com%= net%":就不能匹配詞序'= 003;倒的xxx.net..x= xx.com

匹配度

有匹配度演算法,= 559;匹配程度(相似度)= ;比較高的結果排在前&#= 38754;。

沒有匹配程度的控= 046;:比如有記錄中net出= ;現5詞= ;和出現1次= ;的,結果是一樣的。

結果輸出

通過特別的演算法A= 292;將最匹配度最高的頭= ;100條= ;結果輸出,結果集是緩衝式的小批%= 327;讀取的。

返回所有的結果集A= 292;在匹配條目非常多的= ;時候(比如上萬條)&#= 38656;要大量的記憶體存ă= 18;這些臨時結果集。<= span lang=3DEN-US style=3D'font-family:"Trebuchet MS";mso-bidi-font-family:PMi= ngLiU; color:#333333;mso-font-kerning:0pt'>

可定制性= ;

通過不同的語言分= 512;介面實現,可以方便= ;的定制出符合應用需&#= 35201;的索引規則(包括ë= 65;中文的支援)

沒有介面或介面複&= 620;,無法定制

結論

高負載的模糊查詢= 033;用,需要負責的模糊= ;查詢的規則,索引的&#= 36039;料量比較大

使用率低,模糊匹%= 197;規則簡單或者需要模= ;糊查詢的資料量少

全文檢索和= ;資料庫應用最大的不&#= 21516;在於:讓最相關的ƅ= 57;100條結果滿足= ;98%以上用戶的= ;需求

Lucene
的創新之處:

大部分的搜= ;索(資料庫)引擎都&#= 26159;用B<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>樹結構來維= ;護索引,索引的更新&#= 26371;導致大量的IO= 操作,Lucene在實現中,對Ē= 92;稍微有所改進:不是= 維護一個索引檔,而= 6159;在擴展索引的時候ߎ= 1;斷創建新的索引檔,&= #28982;後定期的把這些新= 340;小索引合併到原先௚= 0;大索引中(針對不同&= #30340;更新策略,批次的= 823;小可以調整),這樣= ;在不影響檢索的效率&#= 30340;前提下,提高了索ó= 41;的效率。

Lucene和其他一些全ă= 91;檢索系統/<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>應用的比較= ;:

 

Lucene

其他開源全文檢索= 995;統

增量索引和批量索= 341;

可以進行增量的索= 341;(Append),= ;可以對於大量資料進&#= 34892;批量索引,並且介ƃ= 54;設計用於優化批量索= 引和小批量的增量索= 4341;。

很多系統只支援批%= 327;的索引,有時資料源= ;有一點增加也需要重&#= 24314;索引。

數據源

Lucene沒有定義具體的資= 009;源,而是一個文檔的結= 083;,因此可以非常靈活= ;的適應各種應用(只&#= 35201;前端有合適的轉換Ý= 20;把資料源轉換成相應= 結構),

很多系統只針對網&= 913;,缺乏其他格式文檔的靈= 963;性。

索引內容抓取

Lucene的文檔是由= ;多個欄位組成的,甚&#= 33267;可以控制那些欄位Ƃ= 56;要進行索引,那些欄= 位不需要索引,近一= 7493;索引的欄位也分為༙= 6;要分詞和不需要分詞&= #30340;類型:
  
需要進"= 892;分詞的索引,比如:= ;標題,文章內容欄位
  
不需要$= 914;行分詞的索引,比如= ;:作者/日= ;期欄位

缺乏通用性,往往將文檔整個索= 341;了

語言分析

通過語言分析器的= 981;同擴展實現:
可以過濾þ= 81;不需要的詞:an the of 等= ;,
西文語法Ñ= 98;析:將jumps jumped jumper都歸結成jump進= ;行索引/檢= ;索
非英文支ý= 45;:對亞洲語言,阿拉= 伯語言的索引支援

缺乏通用介面實現

查詢分析

通過查詢分析介面= 340;實現,可以定制自己= ;的查詢語法規則:
比如: 多個關%= 749;字之間的 + - and or關= ;係等

 

併發訪問

能夠支援多用戶的= 351;用

  

關於亞洲語= ;言的切分詞問題(Word Segment)

對於中文來= ;說,全文索引首先還&#= 35201;解決一個語言分析į= 40;問題,對於英文來說= ,語句中單詞之間是= 2825;然通過空格分開的ᦁ= 2;但亞洲語言的中日韓&= #25991;語句中的字是一個字挨一個,所੍= 7;,首先要把語句中按<= /span>進行索引的= ;話,這個詞如何切分出來स= 1;是一個很大的問題。<= /span>

首先,肯定= ;不能用單字元作(si-gram)為索引單元= ;,否則查上海時,不能讓= ;含有海上也匹配。=

但一句話:= ;北京天安門= ;,電腦如何= ;按照中文的語言習慣&#= 36914;行切分呢
北&= #20140; 天安門還是 天安門?讓電腦能夠ý= 53;照語言習慣進行切分,往ঌ= 8;需要機器有一個比較&= #35920;富的詞庫才能夠比$= 611;準確的識別出語句中= ;的單詞。

另外一個解= ;決的辦法是採用自動切分演算法:將單詞按照2<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>元語法(bigram)方式切分出來,比如:=
"
北&= #20140;天安門" = =3D=3D> "北&= #20140; 京天
天安 安門"

這樣,在查= ;詢的時候,無論是查&#= 35426;"北京" 還是查詢= "天安門",將查詢片= ;語按同樣的規則進行切分"北京""天安安門= ",多個關鍵= ;字之間按與"and"的關係組合= ;,同樣能夠正確地映&#= 23556;到相應的索引中。Ű= 89;種方式對於其他亞洲= 語言:韓文,日文都= 6159;通用的。

基&= #26044;自動切分的最࣪= 3;優點是沒有詞表維護ৎ= 4;本,實現簡單,缺點&= #26159;索引效率低,但對= 044;中小型應用來說,基= ;於2<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>元語法的切分還是夠用的= ;。基於2元切分後的索引一般大ë= 67;和原始檔案差不多,= 而對於英文,索引一般只有原ਧ= 1;件的30%-40%不同,

 

自動切分

詞表切分

實現

實現非常簡單

實現複雜

查詢

增加了查詢分析的#= 079;雜程度,

適於實現比較複雜= 340;查詢語法規則

存儲效率

索引冗餘大,索引= 190;乎和原文一樣大

索引效率高,為原= 991;大小的30%= ;左右

維護成本

無詞表維護成本

詞表維護成= ;本非常高:中日韓等&#= 35486;言需要分別維護。
還需要包括詞頻統計= 561;內容

適用領域

嵌入式系統:運行= 872;境資源有限
分散式系Ł= 13;:無詞表同步問&= 988;
多語言環â= 59;:無詞表維護成= 412;

對查詢和存儲效率#= 201;求高的專業搜索引擎= ;

目前比較大= ;的搜索引擎的語言分&#= 26512;演算法一般是基於É= 97;上2<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>個機制的結= ;合。關於中文的語言&#= 20998;析演算法,大家可É= 97;在Google查關鍵字= "wordsegment search"能找到更多相ſ= 64;的資料。

安裝和使用= ;

下載:http://jakarta.apache.org/luc= ene/

注意:Lucene中的一些比較Ş= 79;雜的詞法分析是用<= span class=3DSpellE>JavaCC生成的(<= /span>JavaCCJavaCompilerCompiler,純Java的詞法分析生û= 04;器,所以如果এ= 8;源代碼編譯或需要修&= #25913;其中的QueryParser、定制自己的Ţ= 22;法分析器,還需要從= https://javacc.dev.java.net/下載javacc

lucene的組成結構:ë= 65;於外部應用來說索引= 模組(index)和檢索模組= ;(search)<= /span>是主要的外= ;部應用入口

org.apache.Lucene.search/

搜索入口

org.apache.Lucene.index= /

索引入口

org.apache.Lucene.analysis/

語言分析器

org.apache.Lucene.queryParser<= /span>/

查詢分析器

org.apache.Lucene.document/

存儲結構

org.apache.Lucene.store=

底層IO/存儲結構

org.apache.Lucene.util<= span lang=3DEN-US style=3D'font-family:"Trebuchet MS";mso-bidi-font-family:PMi= ngLiU; color:#333333;mso-font-kerning:0pt'>/

一些公用的資料結= 083;

簡單的例子= ;演示一下Lucene的使用方法:

索&= #24341;過程:從命令行讀= 462;檔案名(多個),將檔分路徑(path欄&= #20301;)和&= #20839;容(body欄&= #20301;)2個&= #27396;位進行存儲,並對= 839;容進行全文索引:索= ;引的單位是Document物&= #20214;,每Document<= /span>物件包含多個欄位Field物&= #20214;,針對不同的欄位= 660;性和資料輸出的需求= ;,對欄位還可以選擇&#= 19981;同的索引/存&= #20786;欄位規則,列表如= 979;:

方法

切詞=

索引

存儲

用途

Field.Text(String name, String value)

Yes

Yes

Yes

切分詞索引並存儲A= 292;比如:標題,內容欄= ;位

Field.Text(String name, Reader value)

Yes

Yes

No

切分詞索引不存儲A= 292;比如:META信= ;息,
不用於返Þ= 38;顯示,但需要進行檢= 索內容

Field.Keyword(String name, String value)

No

Yes

Yes

不切分索引並存儲,比如:日= 399;欄位

Field.UnIndexed(String name, String value)

No

No

Yes

索引,= 482;存儲,比如:路徑

Field.UnStored(String name, String value)

Yes

Yes

No

只全文索引,不存= 786;

public class IndexFiles {=
  //
&#= 20351;用方法:: IndexFiles [索ó= 41;輸出目錄] [索引的檔列表] ...
  public static void main(Stri= ng[] args) throws Exception {
    String indexPath =3D args[0];
    IndexWriter writer;
    //
用= ;指定的語言分析器構&#= 36896;一個新的寫索引器ʌ= 88;第3個參數表示是ࡪ= 2;為追加索引)
    writer =3D new <= span class=3DSpellE>IndexWriter
(indexPath, ne= w SimpleAnalyzer(), false);

    for (int i=3D1; i<args.length; i++) {
      System.out.println("Indexing file " + args[i]);
      InputStream is =3D new FileInput= Stream(args[i]);

      //構造包含2個欄位Field的Document物件
      //一個是路徑path欄位,不= ;索引,只存儲
      //一個是內容body欄位,進行全= 5991;索引,並存儲
      Docu= ment doc =3D new Document();
      doc.add(Field.UnIndexed(&= quot;path", args[i]));
      doc.add(Field.Text("= body", (Reader) new InputStreamReader(is)));
      //將文檔寫入索ং= 1;
      writer.addDocument(doc);
      is.close();
    };
    //
關= ;閉寫索引器
    writer.close();
  }
}
 

索引過程中= ;可以看到:

= ·    語&= #35328;分析器提供了抽象= 340;介面,因此語言分析= ;(Analyser= )是可以定制的ʌ= 92;雖然lucene缺省提供= 2個&= #27604;較通用的分析器SimpleAna= lyserStandardAnalyser,這2個<= span class=3DGramE>分析器缺省都ߎ= 1;支援中文,所以要加&= #20837;對中文語言的切分規則,༙= 6;要修改這2個分析器。

= ·    Lucene並沒有規定資料源௚= 0;格式,而只提供了一&= #20491;通用的結構(Document物件)來接受ŀ= 34;引的輸入,因此輸入= 的資料源可以是:資= 6009;庫,WORD文檔PDF文檔HTML文檔只要能夠設計İ= 56;應的解析轉換器將資= 料源構造成成Docuement= 物件即可進行ŀ= 34;引。

= ·    對&= #26044;大批量的資料索引A= 292;還可以通過調整IndexerWr= ite的檔合併頻率ì= 60;性(mergeFact= or)來提高批量ŀ= 34;引的效率。

檢索過程和= ;結果顯示:

搜索結果返= ;回的是Hits物件,可以= ;通過它再訪問Document= =3D=3D>Field中的內容。= ;

假設根據= body欄位進行全= ;文檢索,可以將查詢&#= 32080;果的path欄位和相應= ;查詢的匹配度(score)列印出來,= ;

public class Search {
  public static void main(Stri= ng[] args) throws Exception {
    String indexPath =3D args[0], queryString
=3D args[1];<= br>     //指向索引目錄į= 40;搜索器
    Searcher searcher =3D new IndexSearcher(indexPath);
    //
查= ;詢解析器:使用和索&#= 24341;同樣的語言分析器
    Query query =3D QueryParser.parse(queryString, "body",
       =           =             &nb= sp;new SimpleAnalyzer());
    //
搜= ;索結果使用Hits存儲
    Hits hits =3D searcher.search(= query);
    //
通= ;過hits可以訪問到相= 5033;欄位的資料和查詢௚= 0;匹配度
    for (int i=3D0; i<hits.length(); i++) {
      System.out.println(hits.doc(i).get("path") + "; Score: " +
        =              =     hits.score(i));
    };
  }
}

在&= #25972;個檢索過程中,語#= 328;分析器,查詢分析器= ;,甚至搜索器(Searcher)&= #37117;是提供了抽象的介&= 754;,可以根據需要進行= ;定制。

Hacking <= span class=3DSpellE>Lucene

簡化的查詢= ;分析器

個人感覺= lucene成為JAKARTA項目後,畫在É= 02;太多的時間用於調試日趨ඳ= 9;雜QueryParser,而其中大部Ñ= 98;是大多數用戶並不很= 熟悉的,目前LUCENE支援的語法= ;:

Query ::=3D ( Clause )*
Clause ::=3D ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")")

中間的邏輯= ;包括:and or + - &&||等&= #31526;號,而且還有"短&= #35486;查詢"和針對西文= ;的首碼/模糊查詢等,Ì= 91;人感覺對於一般應用= 來說,這些功能有一= 0123;華而不實,其實能ࣩ= 6;實現目前類似於Google的查詢語句= ;分析功能其實對於大&#= 22810;數用戶來說已經夠É= 02;。所以,Lucene早期版本的QueryParser仍是比較好的ű= 84;擇。

添加修改刪= ;除指定記錄(Document<= /span>

Lucene提供了索引的Ă= 44;展機制,因此索引的= 動態擴展應該是沒有= 1839;題的,而指定記錄௚= 0;修改也似乎只能通過&= #35352;錄的刪除,然後重= 032;加入實現。如何刪除= ;指定的記錄呢?刪除&#= 30340;方法也很簡單,只ą= 59;需要在索引時根據資= 料源中的記錄ID= 專門另建索= ;引,然後利用IndexReader.delete(Termterm= )方法通過這= ;個記錄ID= 刪除相應的= ;Document<= /span>

根據某個欄= ;位值的排序功能

lucene缺省是<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>按照自己的= ;相關度演算法(score)進行結果= ;排序的,但能夠根據&#= 20854;他欄位進行結果排ò= 07;是一個在LUCENE的開發郵件= ;列表中經常提到的問&#= 38988;,很多原先基於資Ą= 09;庫應用都需要除了基= 於匹配度(score)以外的排= ;序功能。而從全文檢&#= 32034;的原理我們可以瞭Š= 99;到,任何基於索引的ਂ= 8;索過程效率都會導致&= #25928;率非常的低,如果= 522;於其他欄位的排序需= ;要在搜索過程中訪問&#= 23384;儲欄位,速度回大ä= 23;降低,因此非常是不= 可取的。

但這= 5023;也有一個折中的解= ;決方法:在搜索過程&#= 20013;能夠影響排序結果į= 40;只有索引中已經存儲= 的docIDscore2個參數,所以ʌ= 92;基於score以外的排序= ;,其實可以通過將資&#= 26009;源預先排好序,然後੬= 1;據docID進行排序來實Ĩ= 94;。這樣就避免了在<= span lang=3DEN-US style=3D'font-size:8.5pt;line-height:130%;font-family:"Trebuch= et MS"; mso-bidi-font-family:PMingLiU;color:#333333;mso-font-kerning:0pt'>LUCENE搜索結果外= ;對結果再次進行排序&#= 21644;在搜索過程中訪問Ç= 81;在索引中的某個欄位= 值。

裏需要修改的是IndexSearcher中的HitCollec= tor過程:

...
 scorer.score(new HitCollector() {
        = private float minScore =3D 0.0f;
        = public final void collect(int doc, float score) {
        =   if (score > 0.0f &&&= nbsp;           &nbs= p;      // ignore zeroed buckets
        =       (bits=3D= =3Dnull || bits.get(doc))) {&nbs= p;         // skip docs not in bits
        =     t= otalHits[0]++;
        =     if (score >=3D minScore) {
        =       /*
原先:LucenedocID和相ে= 3;的匹配度score例入結= ;果命中列表中:
        =        * hq.put
(new ScoreDoc(doc, = score));      // update hit queue
        =        *
如果用doc û= 10; 1/doc 代替 score= ,就實現了根據docID&#= 38918;排或逆排
        =        *
假設資料源索引= 6178;已經按照某個欄位৵= 0;好了序,而結ੜ= 4;根據docID排序ߖ= 3;就實現了
        =        *
針對某個欄位的= 5490;序,甚至可以實現ੋ= 6;複雜的scoredo= cID的擬合。
        =        */
        =       hq.put(new ScoreDoc(doc, (float)= 1/doc ));
        =       if (hq.size() > nDocs) {          // if hit queue overfull
       &= nbsp;       hq.pop();  =             &nb= sp;         // remove lowest in hit queue
       &= nbsp;       minScore =3D ((ScoreDoc)<= span class=3DSpellE>hq.top
()).score; // reset minSco= re
        =       }
        =     }
        =   }
        = }
      }, <= span class=3DSpellE>reader.maxDoc());

更通用的輸= ;入輸出介面

雖然lucene沒有定義一= ;個確定的輸入文檔格式ᦁ= 2;但越來越多的人想到&= #20351;用一個標準的中間= 684;式作為Lucene的資料導入介ƃ= 54;,然後其他資料,比= 如PDF只需要通過= ;解析器轉換成標準的&#= 20013;間格式就可以進行Ũ= 39;料索引了。這個中間= 格式主要以XML為主,類似= ;實現已經不下4<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>,5個:

數據源: WORD       PDF<= span style=3D'mso-spacerun:yes'>     HTML    DB       othe= r
       =   \        =   |     &nbs= p; |      |         /
        =             &nb= sp;  XML
中間格式
        =             &nb= sp;       |
        =              Lucene INDEX

目前還沒有= ;針對MSWord文&= #27284;的解析器,因= ;為Word文&= #27284;和基於ASCIIRTF= 文檔不同= ,需要使用= ;COM物件機制解= ;析。這個是我在Google上查的相關= ;資料:h= ttp://www.intrinsyc.com/products/enterprise_applications.asp
另&= #22806;一個辦法就是把Word文&= #27284;轉換texthttp://www.winfield.dem= on.nl/index.html


索&= #24341;過程優化

索引一般分= ;2<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>種情況,一= ;種是小批量的索引擴&#= 23637;,一種是大批量的ŀ= 34;引重建。在索引過程= 中,並不是每次新的DOC加入進去索= ;引都重新進行一次索&#= 24341;檔的寫入操作(檔I/O是一件非常= ;消耗資源的事情)。

Lucene先在記憶體中ű= 14;行索引操作,並根據= 一定的批量進行檔的= 3531;入。這個批次的間༎= 8;越大,檔的寫入次數&= #36234;少,但佔用記憶體= 371;很多。反之佔用記憶= ;體少,但檔IO= 操作頻繁,= ;索引速度會很慢。在IndexWriter中有一個MERGE_FACTOR參數可以幫= ;助你在構造索引器後&#= 26681;據應用環境的情況Ð= 05;分利用記憶體減少檔= 的操作。根據我的使= 9992;經驗:缺省Indexer是每20條記錄索引後ë= 31;入一次,每將MERGE_FACTOR增加50倍,索引速度Ö= 87;以提高1<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>倍左右。=

搜索過程優= ;化

lucene支援記憶體索ó= 41;:這樣的搜索比基於= 檔的I/O有數量級的= ;速度提升。
http://www.onjava.com/lpt/a= /3273
而&= #30433;可能減少IndexSearcher的創建和對搜ŀ= 34;結果的前臺的緩存也是ও= 7;要的。

Lucene面向全文檢索į= 40;優化在於首次索引檢= 索後,並不把所有的= 5352;錄(Document<= /span>)具體內容= ;讀取出來,而起只將&#= 25152;有結果中匹配度最ƌ= 40;的頭100條結果(= TopDocs)的ID放到結果&= #38598;緩存中並返回,Ű= 89;可以比較一ߍ= 9;資料庫檢索:如果是&= #19968;個10,000條的資料庫= ;檢索結果集,資料庫&#= 26159;一定要把所有記錄Ð= 39;容都取得以後再開始= 返回給應用結果集的= 2290;所以即使檢索匹配ಟ= 7;數很多,Lucene的結果集佔用į= 40;記憶體空間也不會很= 多。對於一般的模糊= 7298;索應用是用不到這࿟= 6;多的結果的,頭100條已經可以= ;滿足90%以上的檢索= ;需求。

如果首批緩存結果數用完= ;後還要讀取更後面的&#= 32080;果時Searcher<= /span>會再次檢索= ;並生成一個上次的搜&#= 32034;緩存數大1的緩存<= /span>,並再重新向後抓Ö= 62;。所以如果構造一個= Searcher<= /span>去查1120條結果,Searcher其實是進行= ;了2<= span style=3D'font-size:8.5pt;line-height:130%;font-family:PMingLiU;mso-ascii-fo= nt-family: "Trebuchet MS";mso-hansi-font-family:"Trebuchet MS";mso-bidi-font-family:PM= ingLiU; color:#333333;mso-font-kerning:0pt'>次搜索過程= ;:頭100條取完後緩存結&= #26524;用完,Searcher<= /span>重新檢索再= ;構造一個200條的= 2080;果緩存,依此類推= ;,400條緩存800條緩存。由於每次= ;Searcher<= /span>物件消失後= ;,這些緩存也訪ࢇ= 9;那到了,你有ࡤ= 7;能想將結果記錄緩存下來ᦁ= 2;緩存數儘量保෭= 7;在100以下以充分= ;利用首次的結果緩存,不෵= 1;Lucene浪費多次檢索ʌ= 92;而且可以分級進行結果緩存

Lucene的另外一個特Ɩ= 70;是在收集結果的過程= 中將匹配度低的結果= 3258;動過濾掉了。這也਷= 9;和資料庫應用需要將&= #25628;索的結果全部返回= 981;同之處。

我的一些嘗= 試

= ·    支&= #25588;中文的Tokenizer= :這&#= 26377;2個版本,一個是通๮= 2;JavaCC生成的,對CJK部分按一個字元一ࠁ= 1;TOKEN索引,另外一Ì= 91;是從SimpleTok= enizer改寫的,對英ă= 91;支援數位和字母TOKEN,對中文按迭É= 95;索引。

= ·    基&= #26044;XML資料源的索引器:XMLIndexe= r,因此所有資Ą= 09;源只要能夠按照DTD轉換成指定的XML,就可以用XMLIndxer進行索引了。

= ·    根&= #25818;某個欄位排序:按#= 352;錄索引順序排序結果= ;的搜索器:IndexOrde= rSearcher,因此如果需Š= 01;讓搜索結果根據某個= 欄位排序,可以讓資= 6009;源先按某個欄位排ࣲ= 9;序比如:PriceField,這樣索引後ʌ= 92;然後在利用這個按記= 錄的ID順序檢索的搜索器ᦁ= 2;結果就是相當於是那&= #20491;欄位排序的結果了 = 290;

Lucene學到更多=

Luene的確是一個面ë= 65;物件設計的典範

= ·    所&= #26377;的問題都通過一個&= 989;外抽象層來方便以後= ;的擴展和重用:你可&#= 20197;通過重新實現來達Ò= 40;自己的目的,而對其= 他模組而不需要;

= ·    簡&= #21934;的應用入口Searcher, Indexer,並調用底層Ç= 68;系列元件協同的完成= 搜索任務;

= ·    所&= #26377;的物件的任務都非= 120;專一:比如搜索過程= ;:QueryPars= er分析將查詢語Ö= 77;轉換成一系列的精確= 查詢的組合(Query),通過底層的索ó= 41;讀取結構IndexRead= er進行索引的讀Ö= 62;,並用相應的打分器給搜索ಈ= 0;果進行打分/排序等。所有的功೦= 1;模組原子化程度非常&= #39640;,因此可以通過重= 032;實現而不需要修改其= ;他模組。 

= ·    除&= #20102;靈活的應用介面設#= 336;,Lucene還提供了一些ű= 69;合大多數應用的語言= 分析器實現(SimpleAna= lyser,StandardAnalyser),這也是新ī= 92;戶能夠很快上手的重= 要原因之

這些優點都= ;是非常值得在以後的&#= 38283;發中學習借鑒的。Ë= 16;為一個通用工具包,= Lunece的確給予了需Š= 01;將全文檢索功能嵌入= 到應用中的開發者很= 2810;的便利。

此&= #22806;,通過對Lucene的學習和使用ʌ= 92;我也更深刻地理解ߚ= 2;為什麼很多資料庫優&= #21270;設計中要求,比如A= 306;

= ·    盡&= #21487;能對欄位進行索引= 358;提高查詢速度,但過= ;多的索引會對資料庫&#= 34920;的更新操作變慢,Ň= 80;對結果過多的排序條= 件,實際上往往也是= 4615;能的殺手之

= ·    很&= #22810;商業資料庫對大批%= 327;的資料插入操作會提= ;供一些優化參數,這&#= 20491;作用和索引器的merge_fac= tor的作用是類似į= 40;,

= ·    20%/80%原&= #21063;:查的結果多並不= 561;於品質好,尤其對於= ;返回結果集很大,如&#= 20309;優化這頭幾十條結ĉ= 24;的品質往往才是最重= 要的。

= ·    盡&= #21487;能讓應用從資料庫= 013;獲得比較小的結果集= ;,因為即使對於大型&#= 36039;料庫,對結果集的Ɓ= 68;機訪問也是一個非常= 消耗資源的操作。

參考資料:= ;

Apache: L= ucene Project
http://jakarta.apache.org/= lucene/
Lucene
開發/用戶郵件列表ē= 12;檔
L= ucene-dev@jakarta.apache.org
= Lucene-user@jakarta.apache.org

The Lucen= e search engine: Powerful, flexible, and free
http://www.javaworld.com/javaworld/jw-09-2000/jw-0915-Lucene_p.html=

Lucene Tutorial
http://www.= darksleep.com/puff/lucene/lucene.html

Notes on distributed searching with Lucene
http://home.clara.= net/markharwood/lucene/

中文語言的= ;切分詞
http://www.google.com/search?sourceid=3Dnavc= lient&hl=3Dzh-CN&q=3Dchinese+word+segment
=

搜索引擎工= ;具介紹
http://searchtools.com/

Lucene作者Cutting的幾篇論文和ë= 60;利
http://lucen= e.sourceforge.net/publications.html 

Lucene.NET實現:<= span class=3DGramE>dotLucene
http://sourceforg= e.net/projects/dotlucene/

Lucene作者Cutting的另外一個項İ= 46;:基於Java的搜索引擎= ;Nutch
http://www.nutch.org/   http://sourceforge.net/p= rojects/nutch/

關於= 2522;於詞表N-Gram的切分詞比= ;較
http://china.nikkeibp.co.jp/cgi-bin/china/news/int/int200302100112= .html

2005-01-08 CuttingPisa大學&#= 20570;的關於Lucene的講&#= 24231;:非常詳細的Lucene<= /b>架構&#= 35299;說

特別感謝:= ;
前網&#= 26131;CTO許良&#= 20625;(Jack Xu)
給&= #25105;的指導:是您將我= 118;入了搜索引擎這個行= ;業。

原&= #25991;出處:<ahref=3D"http://www.chedong.co= m/tech/lucene.html">http://www.chedong.com/tech/lucene.html</a&g= t;
<<返回 <= o:p>

<<返回首頁<= /span>

------=_NextPart_01C5A13C.E9AE6F80 Content-Location: file:///C:/9FC05CDD/file4029.files/image001.gif Content-Transfer-Encoding: base64 Content-Type: image/gif R0lGODlhWAAfAMQAAE5fTm6CbqmzqdTZ1HOEc2l6afT29J6qnurs6n6Nft/j37/Gv8nQybS9tJSg lImXiSozKi42Li02LUdVR////wAAAF5xXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAA AAAALAAAAABYAB8AAAX/YCWOZGmeaKqubOu+cCzPdG2zVE5V+t7rvJyoxwsKd0Ug0eg7Kp3HoXEq HSF9VaxVqs16SddidRwub8VEM5oKTAaZ2bYc2qx7lWOufo28879namBif25faXh8Qn9ph3JcdFNl i099N5eYmZqbNhESn6ChoqOkpaanqKmlED+trq+wsbKztK4BFri5uru8vb6/wMHCvgC3wAQCyQcE w83Oz8HFvwkDOQoIOQPMwBS83brf37/i4rmyvNK9DwYIB7kFBwgGCdzeu+HB5Pbm4OjGuwkMLCjA q4CCeb664bNQjlyre/wgRsRVDle6XQoUEOxVAMGAXvoWUhxZkWKsiQz7/+26mMsBhQe4EmwjANOC S3oqVTokWW/kvZMr/+VqgMCCQXkNDlC4xsyAgH49fOJTaDIHSJQ+s6YMymvAR6UFCBAw0MACzgEL 9i1sqG8c1q1aS7LE5dWCAHJPcw1goFZqTrhXtcb9a1EorgUfxzJgsGCBAgEGmCHIC47q1oaEGc6q +sofL6XMEiQrUCAZTAIUHNgridlc1GetBVuYa9QA318MDAQGHBvwPt+8M9O2S8FdL6Wqf0/9W9J1 ZazLufZaQKHBRlwFGFQfZxV6Zs0gRWZtPhwXZAoDklUzYBya+/fRDO9C5tWrgOvw8+svvL+//2YA ADDBgAQWaOCBCCao4AiCDDaYIAAhAAA7 ------=_NextPart_01C5A13C.E9AE6F80 Content-Location: file:///C:/9FC05CDD/file4029.files/filelist.xml Content-Transfer-Encoding: quoted-printable Content-Type: text/xml; charset="utf-8" ------=_NextPart_01C5A13C.E9AE6F80--