返回目錄:http://www.cnblogs.com/hanyinglong/p/5464604.htmlhtml
本項目Demo已上傳GitHub,歡迎你們fork下載學習:https://github.com/kencery/Lucene_Compass(項目內部有很詳細的註釋)java
a. 當咱們去淘寶或者京東買東西的時候常常會用到搜索功能,而他們海量的數據都是存儲在數據庫的,那麼程序猿在實現這個搜索功能的時候,是如何實現的呢?使用數據庫的like這時候就變得捉襟見肘,根本不能用了,由於查詢速度會很慢,而用戶不會爲了查詢一個東西等待幾十秒或者幾分鐘(正常一我的願意等待的時間大概爲3-5秒),這時候該怎麼實現這樣的查詢呢?git
b. 並且它們的查詢功能也基本都相似,都是查詢的文本內容,都是相同的查詢方式 ,即找出含有指定字符串的資源。github
a. lucene一個成熟的、開源的、高性能,可伸縮的全文信息搜索庫,它可使你的引用程序添加索引和搜索能力數據庫
a.1 全文檢索:計算機程序經過掃描文章中的每個詞,對每個詞創建一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時根據創建的索引查找,並將查找的結果反饋給用戶的檢索方式,在信息檢索工具中,全文檢索是最具通用性和實用性的。apache
b. lucenee的做者Doug Cutting將其貢獻給Apache,成爲Apache基金的一個子項目(http://jakarta.apache.org/lucene/)網絡
c. 基於lucene開源搜索引擎出現了不少,例如(Apache Solr、Elastic Search、Index Tank、Katta、Bobo Search、Compass、Summa、Summa),它們都是使用lucene來實現的,讓咱們可以感覺一下lucene的強大。 數據結構
d. lucene只關注文本的索引和搜索,不處理語意,搜索時英文不區分大小寫架構
e. 全文檢索系統結構(從下圖就能夠領略到全文檢索的精髓所在)。框架
f. 關於lucene的Demo地址:https://github.com/kencery/Lucene_Compass(裏面每一個分支詳細講解了lucene的功能和實現)。
g. 博客中使用的圖片大部分來源於網絡,前輩們畫的已經很是好,看圖就可以理解了,自認爲本身畫的超不過前輩,故而拿來主義了。
a. 假如信息檢索系統在用戶發出了檢索請求後在去數據庫中查找結果,根本沒法再有限的時間內返回結果,全部要先把須要檢索的資源放到本地,而且使用某種特定的數據結構存儲,稱爲索引,這個索引的集合稱之爲索引庫,因爲索引庫的結構是按照專門爲快速查詢設計的,因此查詢的速度很是快,咱們每次搜索都是在本地的索引庫中進行,那麼這時候就出現了數據集合和索引庫的一致性,故而對於全文檢索功能的開發,須要作的有兩個方面:索引庫管理(維護索引庫中的數據)、在索引庫中進行搜索,而Lucene就是操做索引庫的工具。
b. lucene做爲一個全文檢索引擎,其具備如下優勢:
b.1 索引文件獨立於應用平臺。lucene定義了一套以8位字節爲基礎的索引文件格式,使得兼容應用系統和不一樣平臺都可以共享創建的索引文件。
b.2 在傳統全文檢索引擎倒排索引的基礎上,實現了分塊索引,可以針對新的文件創建小文件索引,提高索引速度,而後經過和原來索引的合併,達到優化的目的。
b.3 優秀的面向對象的系統架構,使得對於lucene擴展的學習難度下降,方便擴展新的功能。
b.4 設計了獨立於語言和文件格式的文本分析接口,索引器經過接受Token流完成索引文件的創立,用戶擴展新的語言和文件格式,只須要實現文本分析的接口。
b.5 已經默認實現了一套強大的查詢引擎,用戶無需本身編寫代碼即可以使系統得到強大的查詢能力,Lucene查詢實現中默認實現了關鍵字查詢、範圍查詢、查詢全部、通配符查詢、模糊查詢、短語查詢、布爾查詢。
c. 開源,可擴展能力強,有各類語言版本
a. 系統結構
a.1 lucene的系統由基礎結構封裝,索引核心,對外接口三大部分組成,其中直接操做索引文件的索引核心是整個lucene系統中的重中之重。
b. 包結構
c. Lucene功能強大,可是從根本上來講,仍是主要包含兩塊,一是文本內容經切詞後索引入庫,二是根據查詢條件返回結果。
d. 搭建Lucene的開發環境須要加入Lucene的jar包,在項目開發中要加入的jar包至少要有一下幾個:
lucene-core-5.5.0.jar、lucene-analyzers-common-5.5.0.jar、lucene-highlighter-5.5.0.jar、lucene-memory-5.5.0.jar、lucene-queryparser-5.5.0.jar
e. 對索引庫的操做能夠分爲兩種:管理和查詢,管理索引庫使用IndexWriter,從索引庫中查詢使用IndexSearcher。
a. public abstract class org.apache.lucene.store.Directory
Directory類表明lucene索引的位置,它是一個抽象類,其中含有兩個實現,第一個是FSDirectory,它表示一個存儲在文件系統中的索引的位置,第二個是RAMDirectory,它表示一個存儲在內存當中的索引的位置。
b. public abstract class org.apache.lucene.analysis.Analyzer
b.1 在一個文檔被索引以前,首先須要對文檔內容進行分詞處理,而且剔除一些冗餘的詞句(例如:a,the,they等),這份工做就是有Analyzer來作的。
b.2 Analyzer類是一個抽象類,它有不少實現,請同時按住Ctrl+T查看。
b.3 針對不一樣的語言和應用須要選擇適合的Analyzer,Analyzer把分詞後的內容交給IndexWriter來創建索引。
c. public final class org.apache.lucene.index.IndexWriterConfig
在lucene3.X以上版本中,與前幾個版本不一樣的地方包括了IndexWriter實例的初始化,其中須要用到IndexWriterConfig類,另外從Lucene的API中能夠看到目前IndexWriter類最新的構造函數須要用到IndexWriterConfig類。
d. public final class org.apache.lucene.document.Document
d.1 Document文檔相似數據庫中的一條記錄,能夠由好幾個字段(Field)組成,而且字段能夠套用不一樣的類型
d.2 一個Field表明與這個文檔相關的元數據,元數據如:做者,標題,主題,修改日期等等,分別做爲文檔的字段索引和存儲。
d.3 Document的方法
(1) void add(IndexableField field) 添加一個字段(Field)到Document中
(2) String get(String name) 從文檔中得到一個字段對應的文本。
e. public final class org.apache.lucene.document.TextField
e.1 TextField 對象使用來描述一個文檔的某個屬性的,好比一篇文章的做者和標題,能夠用兩TextField對象分別描述。
e.2 Field.Store—>表示Field的存儲方式
(1) NO—>原文不存儲在索引文件中,搜索結果命中後,在根據其餘附加屬性如文件的Path,數據庫的主鍵等,從新連接打開原文,適合原文內容較大的狀況。
(2) YES—>索引文件原本只存儲索引數據,此設計將原文內容直接也存儲在索引文件中,如文章的標題,內容。
f. public class org.apache.lucene.index.IndexWriter
f.1 IndexWriter是在索引過程當中的中心組件
f.2 IndexWriter 這個類建立一個新的索引而且添加文檔到一個已有的索引中,你能夠把IndexWriter想象成讓你能夠對索引進行寫操做的對象,可是不能讓你讀取或搜索。
f.3 IndexWriter不是惟一的用來修改索引的類。
a. 代碼以在github上開源,地址:https://github.com/kencery/Lucene_Compass
b. 在創建索引時,先要把文檔存到索引庫中,還要更新詞彙表。
1 /** 2 3 * 爲文章創建索引 4 5 * @throws IOException 6 7 */ 8 9 @Test 10 11 public void testCreateIndex() throws Exception { 12 13 //1 將須要添加的實體構形成實體對象 14 15 Article article=new Article(1, "Lucene是全文檢索框架", 16 17 "全文檢索(Full-Text Retrieval)是指以文本做爲檢索對象,找出含有指定詞彙的文本。" + 18 19 "全面、準確和快速是衡量全文檢索系統的關鍵指標。"); 20 21 //2 保存到數據庫(此步驟暫時省略) 22 23 //3 創建索引(lucene) 24 25 Directory directory=FSDirectory.open(Paths.get("./indexDir/")); //索引庫目錄 26 27 Analyzer analyzer=new IKAnalyzer(); //分詞器 28 29 IndexWriterConfig iwc= new IndexWriterConfig(analyzer); 30 31 // >>3.1 將Article轉爲Document 32 33 /** Store參數說明 34 35 No 本字段的原始值不存儲 36 37 YES 本字段的原始值會存在出在數據庫區中 38 39 若是不存在,則搜索出來的結果中這個字段的值爲null */ 40 41 /** 42 43 * 自Lucene4開始 建立field對象使用不一樣的類型 只須要指定是否須要保存源數據 不需指定分詞類別 44 45 * 以前版本的寫法以下 46 47 * doc.Add(new Field("id", article.id.ToString(), Field.Store.YES, Field.Index.ANALYZED)); 48 49 */ 50 51 Document doc=new Document(); 52 53 doc.add(new TextField("id", article.getId().toString(), Store.YES)); 54 55 doc.add(new TextField("title", article.getTitle(), Store.YES)); 56 57 doc.add(new TextField("content", article.getContent(), Store.YES)); 58 59 // >>3.2 保存到索引庫中 60 61 IndexWriter indexWriter=new IndexWriter(directory,iwc); 62 63 indexWriter.addDocument(doc); 64 65 indexWriter.close(); //釋放資源 66 67 }
c. 索引設置建議
c.1 儘可能減小沒必要要的存儲(不須要的字段就不要存儲在索引庫中)
c.2 不須要檢索的內容建議不要創建索引
c.3 非文本格式須要提早轉化
a.Lucene的索引存儲位置使用的是一個接口(抽象類),也就能夠實現各類各樣的實際存儲方式(實現類,子類),好比存放在文件系統中,存放在內容中,存放在數據庫中等,Lucene提供了兩個子類:FSDirectory和RAMDirectory
a.1 FSDirectory 存放在文件系統中,是真實的文件夾和文件。
a.2 RAMDirectory 存放在內存中,是模擬的文件夾和文件,與FSDirectory相比含有一下差別(1.由於沒有IO曹鄒,因此速度快,2.由於在內存中存放,因此在程序退出後索引庫數據就不存在了)。
但願你們能從中間學到東西,若有疑問,請留言或者去GitHub上看LuceneDemo或者添加個人QQ,咱們共同探討。