1. 全文檢索介紹
1.1. 全文檢索是什么
終於有時間來介紹一下之前學過的全文檢索了。按照百度上的解釋,全文檢索的概念是:
全文檢索是計算機程序通過掃描文章中的每一個詞,對每一個詞建立一個索 引,指明該詞在文章中出現的次數和位置。當用戶查詢時根據建立的索引查 找,類似於通過字典的檢索字表查字的過程。
通俗來說,全文檢索就是分解查詢條件的信息,然后查詢出跟分解查詢條件后的信息匹配的信息記錄。最好的例子就是百度:
通過將查詢條件“在你來之前我們已經是冠軍了”分解成“在你來之前”、“已經是”、“冠軍了”等信息再去匹配相關信息查詢出來。這種搜索方式就是全文檢索。
1.2. 全文檢索和數據庫查詢有什么不同
看到這里,也許會有人會說全文檢索和數據庫查詢都是查詢,應該差別不大吧!
這其中的差別可以用下面表情包來表達了。
如果數據庫能夠很好地解決全文檢索的問題,那就應該不會有lucene的出現了。數據庫查詢的方式比較古板,最多就是能前后匹配,限制比較大。
select xxx from xxx where xxx like ‘%在你來之前我們已經是冠軍了%’
這樣的語句查詢條件多一個字和少一個子的查詢結果差別比較大。而且當數據比較大,遇到上千萬過億的數據的時候,數據庫查詢的效率會比較低。
而全文檢索恰好就是為了應對這種情況而誕生的。
全文檢索可以處理上億的數據而保持效率,並且搜索出來的結果會更智能。
2. Lucene介紹
Lucene是什么呢?為什么要介紹它呢?
因為Lucene是一套用於全文檢索和搜尋的開源程序庫,由Apache軟件基金會支持和提供。Lucene提供了一個簡單卻強大的應用程序接口(API),能夠做全文索引和搜尋,在Java開發環境里Lucene是一個成熟的免費開放源代碼工具。
當然也可以用Solr和Elasticsearch來開發,但這里講的是用lucene來開發,其它的就不展開了。不過值得一提的是,Solr和Elasticsearch都是基於Lucene開發的搜索引擎產品。
2.1. Lucene實現全文檢索原理
這里簡單說一下Lucene實現全文檢索的原理:
Lucene技術可以類比構造一個數據庫,但lucene是通過獲取文本的信息,通過分詞器分詞建立索引構成索引庫(類比數據庫)。然后就可以通過lucene的查詢對象去建立好索引的數據或者文檔了。lucene中的一個document對應數據庫的一條記錄,而一個feild則對應數據庫的一個字段。
注意:lucene適合對純文本(txt)建立索引,理論上對doc,ppt,cls等也可以,但測試結果不佳。對pdf等文件應該使用poi等工具進行數據轉換,再建立索引。
該圖參考來自:https://blog.csdn.net/weixin_42633131/article/details/82873731
2.2. 分詞器
分詞器是lucene中用來對文本信息進行信息提取,建立索引的算法器。雖然lucene本身自備了幾個分詞器,但是只對英文有效,關於中文的效果都不算好。因此這里推薦一個中文分詞器:IKAnalyzer
2.2.1. IKAnalyzer分詞器
IK作為比較老派,且比較出名的中文分詞器。分詞效果好,並且可以拓展新詞是個比較好的選擇。
缺點是自從更新到2012版本后,就停止更新了。盡管有個說法是,IK分詞器已經到達中文分詞的瓶頸了,就是說這個產品已經很完美了,不需要再更新,后面無非是在拓展文件里面添加新詞就可以了。但是,IK分詞器只支持Lucene4版本,不支持后面版本的lucene, 若要支持高版本的lucene則需要對IK分詞器進行源碼修改。
最近在github看到有關的更新,詳情可以查看:https://github.com/magese/ik-analyzer-solr
3. java引入Lucene8.1.0
3.1. 導入相關包
到官網下載Lucene的jar包:http://lucene.apache.org/
到github下載IKAnalyzer的jar包
需要導入的jar包如下:
同時也要引入IKAnalyzer的相關文件:
IKAnalyzer.cfg.xml
ext.dic
stopword.dic
3.1.1. IKAnalyzer.cfg.xml
IKAnalyzer.cfg.xml文件要放在src目錄下,否則分詞器會無法獲取到拓展詞或者停止詞。該文件配置ext.dic和stopword.dic這兩個文件的路徑。
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 4 5 <properties> 6 7 <comment>IK Analyzer 擴展配置</comment> 8 9 <!--用戶可以在這里配置自己的擴展字典 --> 10 11 <entry key="ext_dict">ext.dic;</entry> 12 13 <!--用戶可以在這里配置自己的擴展停止詞字典--> 14 15 <entry key="ext_stopwords">stopword.dic;</entry> 16 17 </properties>
3.1.2. ext.dic
ext.dic是拓展詞庫,分詞器會對拓展詞庫里面的詞語不再分詞。
3.1.3. stopword.dic
stopword.dic是停止詞庫,分詞器會對將與停止詞庫匹配的詞語過濾掉。
3.1.4. 分詞測試
這里可以寫一個方法測試分詞效果:
1 import java.io.IOException; 2 import java.io.StringReader; 3 import org.wltea.analyzer.core.IKSegmenter; 4 import org.wltea.analyzer.core.Lexeme; 5 6 public class IkanalyzerTest { 7 8 private static void analysisString() { 9 10 String text="在你來之前我們已經是冠軍了"; 11 12 StringReader sr = new StringReader(text); 13 14 IKSegmenter ik = new IKSegmenter(sr, true); 15 16 Lexeme lex=null; 17 18 try { 19 20 while((lex=ik.next())!=null){ 21 22 // System.out.print(lex.getLexemeText()+"|"); 23 24 System.out.println(lex.getLexemeText()); 25 26 } 27 28 } catch (IOException e) { 29 30 e.printStackTrace(); 31 32 } finally { 33 34 // 關閉流資源 35 36 if(sr != null) { 37 38 sr.close(); 39 40 } 41 42 } 43 44 } 45 46 47 public static void main(String[] args) { 48 49 analysisString(); 50 51 52 } 53 54 }
測試結果:
加載擴展詞典:ext.dic
加載擴展停止詞典:stopword.dic
在你
來
之前
我們
已經是
冠軍