Apache Lucene(全文檢索引擎)—建立索引

目錄

  返回目錄:http://www.cnblogs.com/hanyinglong/p/5464604.htmlhtml

  本項目Demo已上傳GitHub,歡迎你們fork下載學習:https://github.com/kencery/Lucene_Compass(項目內部有很詳細的註釋)java

1. 發生在咱們身邊的搜索?

  a. 當咱們去淘寶或者京東買東西的時候常常會用到搜索功能,而他們海量的數據都是存儲在數據庫的,那麼程序猿在實現這個搜索功能的時候,是如何實現的呢?使用數據庫的like這時候就變得捉襟見肘,根本不能用了,由於查詢速度會很慢,而用戶不會爲了查詢一個東西等待幾十秒或者幾分鐘(正常一我的願意等待的時間大概爲3-5秒),這時候該怎麼實現這樣的查詢呢?git

  b. 並且它們的查詢功能也基本都相似,都是查詢的文本內容,都是相同的查詢方式 ,即找出含有指定字符串的資源。github

    

2. lucene是什麼呢?

  a. lucene一個成熟的、開源的、高性能,可伸縮的全文信息搜索庫,它可使你的引用程序添加索引和搜索能力數據庫

    a.1 全文檢索:計算機程序經過掃描文章中的每個詞,對每個詞創建一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時根據創建的索引查找,並將查找的結果反饋給用戶的檢索方式,在信息檢索工具中,全文檢索是最具通用性和實用性的。apache

  b. lucenee的做者Doug Cutting將其貢獻給Apache,成爲Apache基金的一個子項目(http://jakarta.apache.org/lucene/)網絡

  c. 基於lucene開源搜索引擎出現了不少,例如(Apache SolrElastic SearchIndex TankKattaBobo SearchCompassSummaSumma),它們都是使用lucene來實現的,讓咱們可以感覺一下lucene的強大。 數據結構

  d. lucene只關注文本的索引和搜索,不處理語意,搜索時英文不區分大小寫架構

  e. 全文檢索系統結構(從下圖就能夠領略到全文檢索的精髓所在)。框架

    

  f. 關於lucene的Demo地址:https://github.com/kencery/Lucene_Compass(裏面每一個分支詳細講解了lucene的功能和實現)。

  g. 博客中使用的圖片大部分來源於網絡,前輩們畫的已經很是好,看圖就可以理解了,自認爲本身畫的超不過前輩,故而拿來主義了。

3. 爲何使用lucene全文檢索呢?

  a. 假如信息檢索系統在用戶發出了檢索請求後在去數據庫中查找結果,根本沒法再有限的時間內返回結果,全部要先把須要檢索的資源放到本地,而且使用某種特定的數據結構存儲,稱爲索引,這個索引的集合稱之爲索引庫,因爲索引庫的結構是按照專門爲快速查詢設計的,因此查詢的速度很是快,咱們每次搜索都是在本地的索引庫中進行,那麼這時候就出現了數據集合和索引庫的一致性,故而對於全文檢索功能的開發,須要作的有兩個方面:索引庫管理(維護索引庫中的數據)、在索引庫中進行搜索,而Lucene就是操做索引庫的工具。

  b. lucene做爲一個全文檢索引擎,其具備如下優勢:

    b.1 索引文件獨立於應用平臺。lucene定義了一套以8位字節爲基礎的索引文件格式,使得兼容應用系統和不一樣平臺都可以共享創建的索引文件。

    b.2 在傳統全文檢索引擎倒排索引的基礎上,實現了分塊索引,可以針對新的文件創建小文件索引,提高索引速度,而後經過和原來索引的合併,達到優化的目的。

    b.3 優秀的面向對象的系統架構,使得對於lucene擴展的學習難度下降,方便擴展新的功能。

    b.4 設計了獨立於語言和文件格式的文本分析接口,索引器經過接受Token流完成索引文件的創立,用戶擴展新的語言和文件格式,只須要實現文本分析的接口。

    b.5 已經默認實現了一套強大的查詢引擎,用戶無需本身編寫代碼即可以使系統得到強大的查詢能力,Lucene查詢實現中默認實現了關鍵字查詢、範圍查詢、查詢全部、通配符查詢、模糊查詢、短語查詢、布爾查詢。

  c. 開源,可擴展能力強,有各類語言版本

4. Lucene系統結構以及包結構

  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。

5. 理解核心索引類

  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不是惟一的用來修改索引的類。

6. 建立一個索引的大體實現

  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 非文本格式須要提早轉化

7. FSDirectory和RAMDirectory的區別

  a.Lucene的索引存儲位置使用的是一個接口(抽象類),也就能夠實現各類各樣的實際存儲方式(實現類,子類),好比存放在文件系統中,存放在內容中,存放在數據庫中等,Lucene提供了兩個子類:FSDirectory和RAMDirectory

    a.1 FSDirectory 存放在文件系統中,是真實的文件夾和文件。

  a.2 RAMDirectory 存放在內存中,是模擬的文件夾和文件,與FSDirectory相比含有一下差別(1.由於沒有IO曹鄒,因此速度快,2.由於在內存中存放,因此在程序退出後索引庫數據就不存在了)。

 

     但願你們能從中間學到東西,若有疑問,請留言或者去GitHub上看LuceneDemo或者添加個人QQ,咱們共同探討。

相關文章
相關標籤/搜索