Java 的開放原碼全文搜尋技術 - Lucene

6,159
-1

Published on

簡介 Java-based 的全文搜尋引擎 Lucene 的概念及基本實作

Published in: Technology, Education
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,159
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
108
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide

Java 的開放原碼全文搜尋技術 - Lucene

  1. 1. Java 的開放原碼全文搜尋技術 - Lucene 作者: 王建興 /Chien-Hsing Wang [email_address]
  2. 2. 個人簡介 <ul><li>清大資工博士候選人 </li></ul><ul><li>研究興趣 </li></ul><ul><ul><li>Distributed Network Management System </li></ul></ul><ul><ul><li>Mobile Code System </li></ul></ul><ul><ul><li>Peer-to-Peer System </li></ul></ul><ul><li>開發興趣 </li></ul><ul><ul><li>J2EE-based System </li></ul></ul><ul><li>Qing </li></ul><ul><ul><li>“ ching” </li></ul></ul>
  3. 3. 概要 <ul><li>全文搜尋引擎簡介 </li></ul><ul><li>Lucene 簡介與程式設計 </li></ul><ul><li>Lucene 應用實例-圖檔管理 </li></ul><ul><li>相關資源 </li></ul>
  4. 4. 全文搜尋引擎簡介 <ul><li>為何需要全文搜尋引擎 </li></ul><ul><li>全文搜尋引擎的基本概念 </li></ul>
  5. 5. 為何需要全文搜尋引擎? <ul><li>你今天 Google 了嗎? </li></ul><ul><ul><li>Google 大神無所不在,日日焚香禱祝,便可受其庇祐 </li></ul></ul><ul><li>企業的文件中心 </li></ul><ul><ul><li>文件資料電子化程度高,數量又龐大 </li></ul></ul><ul><li>個人的數位資料管理 </li></ul>
  6. 6. 全文搜尋引擎技術 <ul><li>給定一小段字詞,搜尋含有該字詞的文件 </li></ul><ul><li>作法一: String Matching Algorithm </li></ul><ul><ul><li>所有的文件內容都需保留 </li></ul></ul><ul><ul><li>搜尋速度在規模提升後會衰退的很快 </li></ul></ul><ul><li>作法二: Index-based Method </li></ul>
  7. 7. 全文搜尋流程 文件 查詢結果 索引 排名 查詢 輸入查詢條件 預先的處理
  8. 8. 全文搜尋的查詢 <ul><li>自然語言 </li></ul><ul><ul><li>” 我要找出教 Java 程式設計的文章” </li></ul></ul><ul><li>布林運算表示 </li></ul><ul><ul><li>“ Java” and “ 程式設計” </li></ul></ul>
  9. 9. 全文搜尋中預先的處理動作 <ul><li>依文件格式解出文件中的文字部份 </li></ul><ul><ul><li>例如: Word, PDF, HTML, etc… </li></ul></ul><ul><li>斷字斷詞 </li></ul><ul><ul><li>東西大不同 </li></ul></ul><ul><li>建索引 </li></ul>
  10. 10. 文件的結構化表示 王森是個好人 文件 1 王建興 , 也是個好人 文件 2 2 好人 ... ... 2 王建興 2 王建 1 好人 1 森是個 ... ... 1 王森是個 1 王森是 1 王森 文件號 詞
  11. 11. 索引表示- Vector Space 2 5 1 0 0 4 1 1 0 1 0 3 1 0 0 3 10 2 4 2 0 0 3 1 詞 5 詞 4 詞 3 詞 2 詞 1 文件號
  12. 12. 索引表示- Inverted Index (1/3) 2 1 1 4 詞 5 5 1 0 2 詞 4 1 0 0 0 詞 3 0 1 3 0 詞 2 0 0 10 3 詞 1 文件 4 文件 3 文件 2 文件 1 詞
  13. 13. 索引表示- Inverted Index (2/3) 4 1 詞 5 1 2 詞 5 1 3 詞 5 5 4 詞 4 1 3 詞 4 1 3 詞 2 10 2 詞 1 2 4 詞 5 2 1 詞 4 5 4 詞 3 3 2 詞 2 3 1 詞 1 頻率 文件號 詞
  14. 14. 索引表示- Inverted Index (3/3) 8 3 詞 4 8 4 詞 5 5 1 詞 3 4 2 詞 2 13 2 詞 1 總頻率 文件數 詞 4 1 1 2 1 3 5 4 1 3 1 3 10 2 2 4 2 1 5 4 3 2 3 1 頻率 文件號
  15. 15. 索引式方法 VS. Like <ul><li>RDMS 的 like , DB 的索引是起不了作用的 </li></ul><ul><ul><li>僅用 GREP 式的搜尋 </li></ul></ul><ul><li>like 不具斷詞的比對效果 </li></ul><ul><ul><li>Like def% 有可能找出 definition 與 definite </li></ul></ul><ul><li>like 不能提供比對結果的好壞指標 </li></ul><ul><ul><li>不具衡量相似性的能力 </li></ul></ul>
  16. 16. Lucene 簡介與程式設計 <ul><li>Lucene 簡介 </li></ul><ul><li>Lucene 程式設計 </li></ul>
  17. 17. Lucene 是… <ul><li>Lucene 是個高效能的全文搜尋引擎 </li></ul><ul><li>100% Pure Java </li></ul><ul><ul><li>跨平台! </li></ul></ul><ul><li>目前是 Jakarta Project 的一部份 </li></ul><ul><ul><li>Open Source </li></ul></ul><ul><ul><li>Free </li></ul></ul>
  18. 18. Lucene 的作者與歷史 <ul><li>作者 : Doug Cutting </li></ul><ul><ul><li>V-Twin 搜尋引擎的首席開發者 </li></ul></ul><ul><ul><li>Excite 的資深系統架構師 </li></ul></ul><ul><li>歷史沿革 </li></ul><ul><ul><li>www.lucene.com </li></ul></ul><ul><ul><li>sourceforge.net/projects/lucene </li></ul></ul><ul><ul><li>jakarta.apache.org/lucene </li></ul></ul>
  19. 19. Powered By Lucene
  20. 20. Powered by Lucene – Jute
  21. 21. Powered by Lucene – 博客中國
  22. 22. Powered by Lucene – 焦點網狂搜
  23. 23. Lucene 的主要特色 <ul><li>提供高效能的索引機制 </li></ul><ul><li>提供布林運算查詢 </li></ul><ul><li>提供查詢結果的排名( ranking )與評分 </li></ul><ul><li>跨平台 </li></ul><ul><li>開放易用的 API </li></ul><ul><li>極易擴充,客製 </li></ul>
  24. 24. Lucene 做為全文搜尋引擎的優點 (1/2) <ul><li>支援遞增式的索引 </li></ul><ul><ul><li>毋需每次重建索引,即使只增加一點資料 </li></ul></ul><ul><li>不侷限在特定型態的資料來源 </li></ul><ul><ul><li>例如 HTML </li></ul></ul><ul><ul><li>可自行剖析不同的資料來源,轉化成可供 Lucene 處理的文件類別 </li></ul></ul><ul><li>文件的多欄索引控制 </li></ul><ul><ul><li>可將文件劃分為多個欄位 </li></ul></ul><ul><ul><li>每個欄位都可進行不同的索引控制,例如斷詞與否 </li></ul></ul>
  25. 25. Lucene 做為全文搜尋引擎的優點 (2/2) <ul><li>提供通用的文件分析能力 </li></ul><ul><ul><li>可自訂文件分析的方式 </li></ul></ul><ul><ul><li>標準支援 CJK 與阿拉伯語言等非拉丁語系的語言 </li></ul></ul><ul><li>提供通用的查詢分析能力 </li></ul><ul><ul><li>可自訂查詢的語法 </li></ul></ul>
  26. 26. Lucene 的安裝與建置 <ul><li>自 Lucene 官方網站取得 </li></ul><ul><ul><li>Binaries :直接可用 </li></ul></ul><ul><ul><li>Source Code :需自行編譯 </li></ul></ul><ul><li>毋需額外的其他 Third Party 程式庫 </li></ul><ul><li>將 library 檔置於 CLASSPATH 中 </li></ul><ul><ul><li>lucene-{version}.jar </li></ul></ul><ul><li>就是這麼簡單! </li></ul>
  27. 27. Lucene 的基本架構 <ul><li>Index </li></ul><ul><li>Query String </li></ul><ul><li>Query </li></ul><ul><li>Searcher </li></ul><ul><li>IndexWriter </li></ul><ul><li>.addDocument() </li></ul><ul><li>Document </li></ul><ul><li>Document </li></ul><ul><li>Document </li></ul><ul><li>QueryParser </li></ul><ul><li>.parse() </li></ul><ul><li>Document </li></ul><ul><li>Field1(name, value) </li></ul><ul><li>Field2(name, value) </li></ul><ul><li>… . </li></ul><ul><li>Keyword1(name, value) </li></ul><ul><li>… . </li></ul>
  28. 28. Lucene 中的文件( Document ) <ul><li>每份文件皆被對應至一文件號( document number ) </li></ul><ul><li>文件是由一組欄位所構成 </li></ul><ul><ul><li>每個欄位皆為 name:value </li></ul></ul><ul><ul><li>例如: </li></ul></ul><ul><ul><ul><li>document.add(Field. Text (“title”, “ 我想當個好人” )); </li></ul></ul></ul><ul><ul><ul><li>document.add(Field. Keyword (“author”, “ 王森” )); </li></ul></ul></ul><ul><ul><ul><li>document.add(Field. Text (“content”, “ 從前我還是個好人的時候…” )); </li></ul></ul></ul>
  29. 29. Lucene 中的欄位( Field ) 1/2 <ul><li>具三種可能的特質 </li></ul><ul><ul><li>Stored :整個欄位值存入,不做索引,只供日後之需 </li></ul></ul><ul><ul><li>Indexed :欄位值會被索引以利搜尋之用 </li></ul></ul><ul><ul><li>Tokenized : Tokenized 的欄位也必須是 Indexed ,這代表此欄位的內容會先經過斷詞的程序 </li></ul></ul>
  30. 30. Lucene 中的欄位( Field ) 2/2 <ul><li>對應至 Field 類別的不同方法 </li></ul><ul><li>各有不同的應用時機 </li></ul><ul><ul><li>省空間不用 Stored 欄位 </li></ul></ul><ul><ul><li>有些欄位毋需斷詞,例如作者 </li></ul></ul>
  31. 31. Field 應用實例 <ul><li>文件中心中的文件有下述欄位 </li></ul><ul><ul><li>檔案位置 ( Stored ) </li></ul></ul><ul><ul><li>作者 ( Indexed ) </li></ul></ul><ul><ul><li>文件時間 ( Stored ) </li></ul></ul><ul><ul><li>文件標題 (Tokenized, Stored ) </li></ul></ul><ul><ul><li>文件內容 ( Tokenized ) </li></ul></ul>
  32. 32. Field 類別的不同方法 N Y Y N Y 儲存 文件內容 Y Y Field.UnStored(String name, String value) 檔案位置 檔案時間 N N Field.UnIndexed(String name, String value) 作者 Y N Field.Keyword(String name, String value) 文件內容 Y Y Field.Text(String name, Reader value) 文件標題 Y Y Field.Text(String name, String value) 例 索引 斷詞 方法
  33. 33. Field 不存在的性質組合 N N Y 儲存 索引等於儲存 斷詞必索引 斷詞必索引 不存在的原因 Y N N Y N Y 索引 斷詞
  34. 34. Lucene 中的分析器( Analyzer ) <ul><li>用於斷詞 </li></ul><ul><ul><li>查詢文字條件 </li></ul></ul><ul><ul><li>文件內容 </li></ul></ul><ul><li>深深影響索引與搜尋的品質 </li></ul><ul><li>有多種預設類型 </li></ul><ul><ul><li>WhileSpaceAnalyzer </li></ul></ul><ul><ul><li>SimpleAnalyzer </li></ul></ul><ul><ul><li>StopAnalyzer </li></ul></ul><ul><ul><li>StandardAnalyzer </li></ul></ul><ul><li>可自訂自己的分析器 </li></ul>
  35. 35. Tokenizer 和 Filter 的作用 <ul><li>Tokenizer </li></ul><ul><ul><li>被 Analyzer 用來把一連串的文字斷成” token” </li></ul></ul><ul><ul><li>This is a book -> “ This ” “is” “a” “book” </li></ul></ul><ul><li>Filter </li></ul><ul><ul><li>對 tokenized 後的 token 進行加工 </li></ul></ul><ul><ul><li>“ This ” “is” “a” “book” -> “ this ” “book” </li></ul></ul><ul><li>Analyzer 可能用到一個以上的 Tokenizer </li></ul><ul><li>但不一定會用到 Filter </li></ul>
  36. 36. 各分析器的差異 (1/2) <ul><li>WhileSpaceAnalyzer </li></ul><ul><ul><li>WhilespaceTokenizer </li></ul></ul><ul><li>SimpleAnalyzer </li></ul><ul><ul><li>LetterTokenizer </li></ul></ul><ul><ul><li>LowerCaseFilter </li></ul></ul><ul><li>StopAnalyzer </li></ul><ul><ul><li>LetterTokenizer </li></ul></ul><ul><ul><li>LowerCaseFilter+StopFilter </li></ul></ul>
  37. 37. 各分析器的差異 (2/2) <ul><li>StandardAnalyzer </li></ul><ul><ul><li>StandardTokenizer </li></ul></ul><ul><ul><li>StandrdFilter+LowerCaseFilter+StopFilter </li></ul></ul>
  38. 38. Lucene 程式設計 <ul><li>加入文件 </li></ul><ul><ul><li>文字解析 </li></ul></ul><ul><ul><li>建立索引 </li></ul></ul><ul><li>搜尋文件 </li></ul><ul><ul><li>搜尋 </li></ul></ul><ul><li>實例說明 </li></ul>
  39. 39. 加入文件 <ul><li>文字解析 </li></ul><ul><ul><li>針對不同格式取出其文字部份 </li></ul></ul><ul><li>建立索引 </li></ul><ul><ul><li>利用 StandardAnalyzer 來分析文件內容 </li></ul></ul><ul><ul><li>利用 Document 與 Field 來輸入文件 </li></ul></ul><ul><ul><li>利用 IndexWriter 來寫入索引 </li></ul></ul>
  40. 40. 加入文件 - 文字解析 WordExtractor extractor = new WordExtractor(); FileInputStream fis = new FileInputStream(f); text = extractor. extractText (fis); fis.close(); <ul><li>使用 org.textmining.text.extraction.WordExtractor </li></ul>
  41. 41. 加入文件 - 建立索引 <ul><li>IndexWriter writer = new IndexWriter(indexPath, </li></ul><ul><li>new StandardAnalyzer (), true); </li></ul><ul><li>Document doc = new Document(); </li></ul><ul><li>doc. add ( Field.UnIndexed (&quot;path&quot;, </li></ul><ul><li>file.getCanonicalPath())); </li></ul><ul><li>doc.add( Field.Text (&quot;text&quot;, text)); </li></ul><ul><li>writer. addDocument (doc); </li></ul><ul><li>writer.close(); </li></ul>
  42. 42. 搜尋文件 <ul><li>對索引進行搜尋 </li></ul><ul><ul><li>利用 StandardAnalyzer 來分析查詢條件 </li></ul></ul><ul><ul><li>利用 QueryParser 來建立 Query 物件 </li></ul></ul><ul><ul><li>利用 IndexSearcher 來對索引進行搜尋 </li></ul></ul><ul><ul><li>利用 Hits 來取得搜尋結果 </li></ul></ul>
  43. 43. 搜尋文件 - 搜尋 <ul><li>Searcher searcher = new </li></ul><ul><li>IndexSearcher (indexPath); </li></ul><ul><li>Query query = </li></ul><ul><li>QueryParser.parse (queryString, </li></ul><ul><li>&quot;text&quot;, new StandardAnalyzer ()); </li></ul><ul><li>Hits hits = searcher. search (query); </li></ul>
  44. 44. 搜尋文件 - 取得搜尋結果 <ul><li>for(int i=0; i<hits.length(); i++) </li></ul><ul><li>{ </li></ul><ul><li>System.out.println(&quot;File:“ </li></ul><ul><li>+hits.doc(i).get(&quot;path&quot;)); </li></ul><ul><li>System.out.println(&quot;tScore:“ </li></ul><ul><li>+hits.score(i)); </li></ul><ul><li>} </li></ul>
  45. 45. Lucene 中的查詢語法 <ul><li>查詢是由詞和運算子所組成 </li></ul><ul><li>所謂的詞( term )即為單一個字詞 </li></ul><ul><ul><li>“ Hello” </li></ul></ul><ul><li>所謂的詞組( phrase )則是由雙引號所括住的多個字詞 </li></ul><ul><ul><li>“ Hello World” </li></ul></ul><ul><li>多詞可經由運算子相連接形成複雜的查詢 </li></ul>
  46. 46. 欄位查詢 <ul><li>“ text” 欄位是預設的欄位 </li></ul><ul><li>title:&quot;The Right Way&quot; AND text:go </li></ul><ul><li>title:&quot;Do it right&quot; AND right </li></ul><ul><li>title:Do it right </li></ul>
  47. 47. 詞之修飾子 (1/2) <ul><li>萬元字元 ? 與 * </li></ul><ul><ul><li>te?t </li></ul></ul><ul><ul><li>test* </li></ul></ul><ul><li>模糊查詢 </li></ul><ul><ul><li>基於 Levenshtein Distance 或 Edit Distance 演算法 </li></ul></ul><ul><ul><li>將 ~ 置於單一字詞之末 </li></ul></ul><ul><ul><li>roam~ 可能找出 foam 和 roams </li></ul></ul>
  48. 48. 詞之修飾子 (2/2) <ul><li>相近搜尋 </li></ul><ul><ul><li>搜尋的字組之間的距離不超過指定的範圍 </li></ul></ul><ul><ul><li>&quot;jakarta apache&quot;~10 </li></ul></ul><ul><li>範圍搜尋 </li></ul><ul><ul><li>基於字串順序 </li></ul></ul><ul><ul><li>mod_date:[20020101 TO 20030101] </li></ul></ul><ul><ul><li>title:{Aida TO Carmen} </li></ul></ul>
  49. 49. 布林運算子 (1/2) <ul><li>OR </li></ul><ul><ul><li>&quot;jakarta apache&quot; jakarta </li></ul></ul><ul><ul><li>&quot;jakarta apache&quot; OR jakarta </li></ul></ul><ul><li>AND </li></ul><ul><ul><li>&quot;jakarta apache&quot; AND &quot;jakarta lucene“ </li></ul></ul><ul><li>+ ,也稱為 required 運算子 </li></ul><ul><ul><li>必須要存在 </li></ul></ul><ul><ul><li>+jakarta apache </li></ul></ul>
  50. 50. 布林運算子 (2/2) <ul><li>NOT </li></ul><ul><ul><li>&quot;jakarta apache&quot; NOT &quot;jakarta lucene&quot; </li></ul></ul><ul><ul><li>NOT “jakarta apache” <- 不 work </li></ul></ul><ul><li>- ,也稱 prohibit 運算子 </li></ul><ul><ul><li>不能存在 </li></ul></ul><ul><ul><li>&quot;jakarta apache&quot; -&quot;jakarta lucene&quot; </li></ul></ul>
  51. 51. Lucene 與中文 <ul><li>中文有不同於拉丁語系的斷詞特殊性 </li></ul><ul><ul><li>自動斷詞 </li></ul></ul><ul><ul><li>詞庫斷詞 </li></ul></ul><ul><li>Lucene 目前標準已支援中文 </li></ul>
  52. 52. Lucene 的客製能力 <ul><li>查詢語法 </li></ul><ul><li>查詢物件的建立 </li></ul><ul><li>斷詞,詞的過濾 </li></ul><ul><li>相似性 (Ranking) </li></ul>
  53. 53. 進階議題 <ul><li>如何處理索引內容的變動 </li></ul><ul><li>刪除已索引的文件 </li></ul><ul><li>縮小索引檔的大小 </li></ul><ul><li>進階的查詢動作 </li></ul><ul><li>調整參數以提昇索引效能 </li></ul><ul><li>於記憶體中進行索引,達到加速的目的 </li></ul>
  54. 54. 索引的變動 <ul><li>重新索引 </li></ul><ul><ul><li>太耗時,不經濟 </li></ul></ul><ul><li>先刪後增 </li></ul><ul><ul><li>刪去變動前的文件 </li></ul></ul><ul><ul><li>新增變動後的文件 </li></ul></ul>
  55. 55. 刪除文件的方式 <ul><li>利用 IndexReader 的 delete() </li></ul><ul><li>delete(int) </li></ul><ul><ul><li>已知文件號 </li></ul></ul><ul><li>delete(Term) </li></ul><ul><ul><li>例如已知檔案路徑 </li></ul></ul>
  56. 56. 索引最佳化 <ul><li>利用 IndexWriter 的 optimize() 方法 </li></ul><ul><li>可壓縮索引資料庫,並提供查詢速度 </li></ul><ul><li>在大量批次索引後可為之 </li></ul><ul><li>毋需每次遞增索引後進行 </li></ul>
  57. 57. 取得 Query 物件的方式 <ul><li>Direct Query Parsing </li></ul><ul><ul><li>利用 QueryParser 將查詢字串轉為 Query 物件 </li></ul></ul><ul><li>Indirect Query Parsing </li></ul><ul><ul><li>將使用者的輸入(受限的)轉為查詢字串,再透過 Direct Query Parsing 取得 Query 物件 </li></ul></ul><ul><li>Query Construction </li></ul><ul><ul><li>自己建構 Query 物件 </li></ul></ul><ul><ul><li>最麻煩但最有彈性 </li></ul></ul>
  58. 58. 提高 Lucene 的索引效能 <ul><li>Indexing Speed Factors </li></ul><ul><ul><li>IndexWriter.mergeFactor </li></ul></ul><ul><ul><ul><li>多少文件索引完後會從 memory 被寫會 disk </li></ul></ul></ul><ul><ul><ul><li>也關係到多個 segment 中的文件數量達到多少時,會被合併成一個 segment </li></ul></ul></ul><ul><ul><ul><li>例如: mergeFactor 為 10 </li></ul></ul></ul><ul><ul><ul><li>10 個文件被寫成一個 segement </li></ul></ul></ul><ul><ul><ul><li>當出現第 10 個 size 為 10 的 segment 時,會被合併成一個 size 為 100 的 segment </li></ul></ul></ul><ul><ul><li>IndexWriter.maxMergeDocs </li></ul></ul><ul><ul><ul><li>單一 segment 中的文件最大量 </li></ul></ul></ul><ul><ul><ul><li>預設為 Integer.MAX_VALUE </li></ul></ul></ul>
  59. 59. In-Memory Indexing <ul><li>RAMDirectory ramDir = new RAMDirectory(); </li></ul><ul><li>IndexWriter ramWriter = new IndexWriter(ramDir, analyzer, true); </li></ul><ul><li>… </li></ul><ul><li>… </li></ul><ul><li>IndexWriter fsWriter = new IndexWriter(indexDir, analyzer, true); </li></ul><ul><li>fsWriter.addIndexes(new Directory[] { ramDir }); </li></ul><ul><li>ramWriter.close(); </li></ul><ul><li>fsWriter.close(); </li></ul>
  60. 60. WebLucene :網站站內搜尋 <ul><li>中國車東 (chedong) 先生所開發 </li></ul><ul><li>可為 Web Site 提供站內的全文搜尋機制 </li></ul><ul><li>當然是 Apache Software License </li></ul><ul><li>http://sourceforge.net/projects/weblucene </li></ul>
  61. 61. Resources (1/2) <ul><li>Project </li></ul><ul><ul><li>http://jakarta.apache.org/lucene/docs/index.html </li></ul></ul><ul><ul><li>[email_address] </li></ul></ul><ul><ul><li>[email_address] </li></ul></ul><ul><li>Index Format </li></ul><ul><ul><li>http://jakarta.apache.org/lucene/docs/fileformats.html </li></ul></ul><ul><li>Introduction </li></ul><ul><ul><li>http://today.java.net/pub/a/today/2003/07/30/LuceneIntro.html </li></ul></ul>
  62. 62. Resources (2/2) <ul><li>Advanced Text Indexing with Lucene </li></ul><ul><ul><li>http://www.onjava.com/pub/a/onjava/2003/03/05/lucene.html </li></ul></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×