本打算直接來學習Solr, 如今先把Lucene的只是捋一遍.
本文內容:html
一、 搜索引擎的發展史java
二、 Lucene入門算法
三、 Lucene的API詳解數據庫
四、 索引調優apache
五、 Lucene搜索結果排名規則api
萌芽:Archie、Gopher緩存
起步:Robot(網絡機器人)和spider(網絡爬蟲)服務器
一、 Robot:網絡機器人,自動在網絡中運行,完成特定任務的程序,如刷票器、搶票軟件等。微信
二、 spider:網絡爬蟲,是一中特殊的機器人,抓取(下載)並分析網絡資源,包括網頁裏面的超鏈接、圖片、數據庫、音頻、視頻等資源信息。網絡
發展:excite、galaxy、yahoo
繁榮:infoseek、altavista、Google、百度
一、 構建文本庫
二、 創建索引
三、 進行搜索
四、 對結果進行排序
搜索引擎的工做原理,經過用戶輸入的信息,經過網絡爬蟲即搜索服務器,將各與之相關的網站信息抓取並存放到本身的數據服務器中,在存入數據服務器的過程中將這些數據信息須要建立索引庫,用戶查詢的結果信息都是來源與索引庫信息,若是點擊該結果超連接則訪問的是該網站信息,若是選擇「快照」則訪問的是緩存信息。
那爲何要創建索引庫呢?創建索引庫的過程就是將該結果創建索引,通俗一點的理解就是創建目錄的過程。
一、 電商網站的搜索,如京東、天貓等
二、 論壇、BBS等站內搜索
三、 垂直領域的搜索,垂直領域:即專門作一件事。如818工做網、拉勾網等都屬於垂直領域。
四、 Windows的資源管理器中的搜索
五、 Word中的Ctrl+F、eclipse中的Ctrl+shift+T等單機軟件的搜索
這些都是屬於信息檢索的範圍。
倒排索引,就是提取信息並創建索引(目錄)的過程當中,搜索時,根據關鍵字找到資源的具體位置。如:
Lucene是apache下的一個開放源代碼的全文檢索引擎工具包。提供了完整的查詢引擎和索引引擎,部分文本分析引擎。Lucene的目的是爲軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能。
全文檢索系統是按照全文檢索理論創建起來的用於提供全文檢索服務的軟件系統。全文檢索系統是一個能夠運行的系統,包括創建索引、處理查詢返回結果集、增長索引、優化索引結構等功能。例如:百度搜索、eclipse幫助搜索、淘寶網商品搜索。
搜索引擎是全文檢索技術最主要的一個應用,例如百度。搜索引擎起源於傳統的信息全文檢索理論,即計算機程序經過掃描每一篇文章中的每個詞,創建以詞爲單位的倒排文件,檢索程序根據檢索詞在每一篇文章中出現的頻率和每個檢索詞在一篇文章中出現的機率,對包含這些檢索詞的文章進行排序,最後輸出排序的結果。全文檢索技術是搜索引擎的核心支撐技術。
Lucene和搜索引擎不一樣,Lucene是一套用java或其它語言寫的全文檢索的工具包,爲應用程序提供了不少個api接口去調用,能夠簡單理解爲是一套實現全文檢索的類庫,搜索引擎是一個全文檢索系統,它是一個單獨運行的軟件系統。
Lucene開源免費,它既不是搜索引擎,也不是可直接運行的軟件,它只是一套API,能夠根據該API開發本身的搜索系統。
這裏咱們使用的是Lucene4.x版本,咱們須要知道是如何建立索引的,並根據輸入的信息將咱們的結果查詢出來這樣的一套流程。
例如BBS貼吧的站內搜索,它是如何完成的呢?難道是查詢數據庫的信息並將結果返回的麼?
官網,http://lucene.apache.org/,咱們經過官網下載咱們須要的jar包。目前最新的版本5.3.1,那這裏咱們使用的是4.10.2這個版本。
解壓咱們的zip壓縮文件,導入咱們須要的jar包。這裏咱們須要分詞器的包、Lucene的核心包、高亮顯示的包和查詢須要的包。
在發帖並提交時,咱們建立帖子的索引庫。
建立索引庫的過程:將文本內容-à轉換成Document對象(該對象中有不少Field,能夠把該Document對象當作是一個帖子),而後在經過IndexWriter建立咱們的索引。
代碼裏提到了分詞器的概念,這個再將API的時候在細說。
咱們經過lukeall工具查看建立的索引庫中的內容。咱們經過java –jar xxx.jar的方式運行咱們的lukeall工具,並經過該工具查看咱們建立的索引庫的內部結構。
目錄庫,分詞後的詞條信息。
也就是內容庫。存放數據的。
檢索過程。
l Directory,指的是文件磁盤的索引路徑
l RAMDirectory,指的是內存中的索引路徑
Analyzer是一個抽象類,在Lucene的lucene-analyzers-common包中提供了不少分析器,好比:org.apache.lucene.analysis.standard.standardAnalyzer標準分詞器,它是Lucene的核心分詞器,它對分析文本進行分詞、大寫轉成小寫、去除停用詞、去除標點符號等操做過程。
什麼是停用詞?停用詞是爲節省存儲空間和提升搜索效率,搜索引擎在索引頁面或處理搜索請求時會自動忽略某些字或詞,這些字或詞即被稱爲Stop Words(停用詞)。好比語氣助詞、副詞、介詞、鏈接詞等,一般自身並沒有明確的意義,只有將其放入一個完整的句子中才有必定做用,如常見的「的」、「在」、「是」、「啊」等。
以下是org.apache.lucene.analysis.standard.standardAnalyzer的部分源碼:
final StandardTokenizer src = new StandardTokenizer(getVersion(), reader);//建立分詞器
src.setMaxTokenLength(maxTokenLength);
TokenStream tok = new StandardFilter(getVersion(), src);//建立標準分詞過濾器
tok = new LowerCaseFilter(getVersion(), tok);//在標準分詞過濾器的基礎上加大小寫轉換過濾
tok = new StopFilter(getVersion(), tok, stopwords);//在上邊過濾器基礎上加停用詞過濾
學過英文的都知道,英文是以單詞爲單位的,單詞與單詞之間以空格或者逗號句號隔開。而中文則以字爲單位,字又組成詞,字和詞再組成句子。因此對於英文,咱們能夠簡單以空格判斷某個字符串是否爲一個單詞,好比I love China,love 和 China很容易被程序區分開來;但中文「我愛中國」就不同了,電腦不知道「中國」是一個詞語仍是「愛中」是一個詞語。把中文的句子切分紅有意義的詞,就是中文分詞,也稱切詞。我愛中國,分詞的結果是:我 愛 中國。
l StandardAnalyzer:
單字分詞:就是按照中文一個字一個字地進行分詞。如:「我愛中國」,
效果:「我」、「愛」、「中」、「國」。
l CJKAnalyzer
二分法分詞:按兩個字進行切分。如:「我是中國人」,效果:「我是」、「是中」、「中國」「國人」。
上面兩個分詞器沒法知足需求。
l SmartChineseAnalyzer
對中文支持較好,但擴展性差,擴展詞庫,禁用詞庫和同義詞庫等很差處理
名稱 |
最近更新 |
速度 ( 網上情報 ) |
擴展性支持、其它 |
mmseg4j |
2013 |
complex 60W 字 /s (1200 KB/s) simple 100W 字 /s (1900 KB/s) |
使用 sougou 詞庫,也可自定義 (complex\simple\ MaxWord) |
IKAnalyzer |
2012 |
IK2012 160W 字 /s (3000KB/s) |
支持用戶詞典擴展定義、支持自定義中止詞 ( 智能 \ 細粒度 ) |
Ansj |
2014 |
BaseAnalysis 300W 字 /s hlAnalysis 40W 字 /s |
支持用戶自定義詞典,能夠分析出詞性,有新詞發現功能 |
paoding |
2008 |
100W 字 /s |
支持不限制個數的用戶自定義詞庫 |
這裏咱們使用IK分詞器。那如何使用IK分詞器呢?
一、 解壓壓縮文件,並將該兩個配置文件放入src中。
二、 導入jar包
導入FF_u1的jar包,該版本支持4.x,而u6僅僅支持4.x以前的版本。
三、 使用該分詞器的先後對比
standardanalyzer:
IKanalyzer :
l LongField,分詞,有多個詞條
l StringField,創建索引時不分詞,將該內容做爲一個完整的詞條Term
l TextField,創建索引時分詞,有多個詞條
l Store:YES或NO不影響是否分詞;YES,會在Document中存儲,NO,不會在Document中存儲
Lucene3.5以後,IndexWriter的初始化有了一個IndexConfig來做爲其初始化的參數,當咱們在使用IndexWrier的時候必定要注意在最後把writer關閉,不然拋出異常。其實這個異常是由於lucene進入到索引目錄中,發現裏面就是一個write.lock。而IndexWriter的構造函數在試圖獲取另一個IndexWriter已經加鎖的索引目錄時就會拋出一個LockObtainFailedException。
當IndexWriter在初始化索引的時候會爲這個索引加鎖,等到初始化完成以後會調用其close()方法關閉IndexWriter,在close()這個方法的內部其實也是調用了unlock()來釋放鎖,當程序結束後IndexWriter沒有正常關閉的時候這個鎖也就沒有被釋放,等待下次對一樣的索引文件建立IndexWriter的時候就會拋出該異常。
執行上面代碼,就會報以下錯誤。
編寫工具類,在使用完IndexWriter後自動關閉。
通俗一點講:就是該對象銷燬後才釋放鎖對象,由於都是將信息放入同一個索引庫中。若是指定不是同一索引庫是沒有問題的,可是須要執行commit方法,由於close方法中包含了commit方法。
檢索最重要的就是根據你的Query去搜索信息,所以咱們Lucene的API中提供了不少的Query對象,咱們根據不一樣的Query對象獨有的特性去檢索咱們須要的信息。
針對單一字段,解析查詢信息並分詞進行搜索。
針對多字段,解析查詢信息並分詞進行搜索。
根據詞條搜索,使用該對象不會在去解析查詢信息並分詞。詞條就是索引庫的最小單位,不可再繼續分詞。
模糊搜索:*表明0個或多個字符;?表明一個字符
類似度搜索,例如,咱們想搜JQuery,可是在輸入框輸入jquary。
FuzzyQuery的構造方法:
FuzzyQuery(Term term):默認支持模糊字數爲2;
FuzzyQuery(Term term, int maxEdits):maxEdits:模糊字數,[0,2]之間,若爲0,至關於TermQuery。
FuzzyQuery(Term term, int maxEdits, int prefixLength):prefixLength,指定要有多個前綴字母必須徹底匹配。
數字範圍搜索(演示:略),最後兩個參數的含義是:minInclusive,是否最小包含,maxInclusive,是否最大包含
查詢全部的結果。
使用Query對象的優先順序
一、 TermQuery,詞條搜索
二、 若輸入內容太長,可用:QueryParser,將輸入內容解析並切詞
三、 若輸入內容太短,可用:WildcardQuery,模糊查詢
四、 若輸入內容有誤,可用:FuzzyQuery,類似度查詢
BooleanQuery,組合查詢,經過該Query對象能夠將上面各類Query進行任意組合。
構造方法:
add(Query query, BooleanClause.Occur occur):query,各類其餘的query;occur,該變量的取值有三種,分別爲:MUST(必須知足)、MUST_NOT(必須不知足)、SHOULD(能夠知足)。
MUST+MUST:兩個Query查詢對象的交集
MUST+MUST_NOT:兩個Query查詢對象的補集
SHOULD+SHOULD:兩個Query查詢對象的並集。
詞條:就是將查詢的信息經過指定的各類Query對象的自己特有的屬性去匹配詞條;
Document:就是將匹配後的結果返回。
索引調優:就是在建立索引時,將咱們的建立的索引庫的內容和磁盤內容加載到內存中,執行完以後,並將內存中的索引庫的內容加載到磁盤上。
RAMDirectory是內存的一個區域,當虛擬機退出後,裏面的內容也會隨之消失
RAMDirectory的性能要好於FSDirectory, 所以能夠結合使用,在虛擬機退出時,將RAM內容轉到FSDirectory。
索引調優代碼:
CREATE:會寫到索引庫並覆蓋原索引庫
CREATE_OR_APPEND:將內存庫信息追加到索引庫中。
idf舉例:
有不少不一樣的數學公式能夠用來計算TF-IDF。這邊的例子以上述的數學公式來計算。詞頻 (TF) 是一詞語出現的次數除以該文件的總詞語數。假如一篇文件的總詞語數是100個,而詞語「母牛」出現了3次,那麼「母牛」一詞在該文件中的詞頻就是3/100=0.03。一個計算文件頻率 (DF) 的方法是測定有多少份文件出現過「母牛」一詞,而後除以文件集裏包含的文件總數。因此,若是「母牛」一詞在1,000份文件出現過,而文件總數是10,000,000份的話,其逆向文件頻率就是 lg(10,000,000 / 1,000)=4。最後的TF-IDF的分數爲0.03 * 4=0.12。
boost,激勵因子,默認值是1,能夠手動更改。咱們能夠設置boost值來改變搜索結果排名。並且設置boost值後,該信息保存在Document文檔的norm中。
查詢的結果:
並且全部的Document中的NORM的值都是同樣。
得分同樣。那麼我想讓第88條記錄排在第一位怎麼辦?咱們只有設置它的激勵因子(boost)值便可。
一、 設置得分
二、 結果
三、 NORM值
設置boost(激勵因子),能夠改變得分以及Norm值。
結果高亮顯示,也就是將搜索內容進行了高亮顯示。例如,百度,查詢java
因此說高亮顯示就是將搜索的信息結果經過HTML標籤進行樣式的處理。能夠對標題也能夠對文本進行高亮顯示。