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


目錄

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

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

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

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

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

    

2. lucene是什么呢?

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

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

  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,我們共同探討。

         


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM