Lucene3.6入門實例

jopen 10年前發布 | 40K 次閱讀 Lucene 搜索引擎

一、簡介
Lucene是什么:Lucene是apache軟件基金會jakarta 項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,即它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引 引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的 功能,或者是以此為基礎建立起完整的全文檢索引擎。

Lucene是一個基于Java的全文搜索,不是一個完整的搜索應用,而是 一個代碼庫和API,可以方便地為應用提供搜索功能。 實際上Lucene的功能就是將開發人員提供的若干個字符串建立索引,然后提供一個全文搜索服務,用戶將搜索的關鍵詞提供給搜索服務,搜索服務告訴用戶關 鍵詞出現的各字符串。

 

二、基本流程

lucene包含兩部分:建立索引和搜索服務。建立索引是將源(本質是字符串)寫入索引或者將源從索引中刪除;進行搜索是向用戶提供全文搜索服務,用戶可以通過關鍵詞定位源。

1、建立索引的流程
使用analyzer處理源字符串,包括:分詞,即分成一個個單詞;去除stopword(可選)。
將源中的有效信息以不同Field的形式加入Document中,并把Document加入索引,從而在索引中記錄有效的Field。

將索引寫入存儲器(內存或磁盤)。

 

2、檢索的流程
用戶提供搜索關鍵詞,經過analyzer處理。
對處理后的關鍵詞搜索索引找出對應的Document。
用戶根據需要從找到的Document中提取需要的Field。 

三、基本概念

  1. Analyzer
    Analyzer的作用是分詞,并去除字符串中的無效詞語。
    分詞的目的是把字符串按某種語義規則劃分為若干個詞。英文中比較容易實現分詞,因為英文本身就是以單詞為單位,已經用空格分開;而中文則必須以某種方法將 連成一片的句子劃分成一個個詞。 無效詞語,如英文中的“of”、“the”和中文中的“的”、“地”等,這些詞語在文章中大量出現。但是本身不包含關鍵信息,去掉后有利于縮小索引文件、 提高命中率和執行效率。

  2. Document
    用戶提供的源可以是文本文件、字符串或者數據庫表中的一條記錄等。一個源字符串經過索引之后,以一個Document的形式存儲在索引文件中。搜索服務的結果也是以Document列表的形式返回。

  3. Field
    一個Document可以包含多個信息域,如一篇文章可以包含“標題”、“正文”、“最后修改時間”等信息域,這些信息域以Field的形式保存在Document中。
    Field有兩個屬性:存儲和索引。存儲屬性可以控制是否對這個Field進行存儲;索引屬性可以控制是否對該Field進行索引。這似乎多此一舉,但事實上對這兩個屬性的正確組合很重要。 

    下面舉例說明:一篇文章需要對標題和正文進行全文搜索,所以把這兩個Field的索引屬性設置為真;同時希望能直接從搜索結果中提取文章標題,所以把標題 Field的存儲屬性設置為真。但是正文Field太大了,為了縮小索引文件,將正文Field的存儲屬性設置為假,需要訪問時再直接讀取文件正文;希望 能從搜索結果中提取最后修改時間;但是不需要對它進行搜索,所以把最后修改時間Field的存儲屬性設置為真,索引屬性設置為假。
    Field的兩個屬性禁止全為假的情況因為這對建立索引沒有意義。

  4. Segment

    建立索引時,并不是每個document都馬上添加到同一個索引文件,它們首先被寫入到不同的小文件,然后再合并成一個大索引文件,每個小文件都是一個Segment。

  5. Term
    Term表示文檔的一個詞,是搜索的最小單位。Term由兩部分組成:所表示的詞語和這個詞語所出現的field。

  6. Token
    Token是term的一次出現,它包含trem文本和相應的起止偏移,以及一個類型字符串。一句話中可以出現多次相同的詞語,它們都用同一個term表示,但是用不同的token,每個token標記該詞語出現的位置。 

    四、Lucene的組成結構

    Lucene包括core和sandbox兩部分,其中core是 lucene的核心,sandbox包含了一些附加功能,如highlighter、各種分析器等。 Lucene core包含8個包:analysis、collation、document、index、queryParser、search、store、 util。

  7. analysis包
    Analysis提供自帶的各種Analyzer,如按空白字符分詞的WhitespaceAnalyzer,添加了stopword過濾的 StopAnalyzer,支持中文分詞的SmartChineseAnalyzer,以及最常用的StandardAnalyzer。

  8. collation包
    包含collationKeyFilter和collationKeyAnalyzer兩個相同功能的類,將所有token轉換為 CollationKey,并將CollationKey與IndexableBinaryStringTools一起編碼存儲為一個term。

  9. document包
    document包中是Document相關的各種數據結構,如Document類、Field類等。

  10. index包
    index包中是索引的讀寫操作類,常用的是對索引文件的segment進行寫、合并和優化的IndexWriter類和對索引進行讀取和刪除操作的 IndexReader類。IndexWriter只關心如何將索引寫入一個個segment并將它們合并優化;IndexReader關注索引文件中 各個文檔的組織形式。

  11. queryParser包
    queryParser包中是解析查詢語句相關的類(常用的是QueryParser類)以及Token類。

  12. search包

    search包中是從索引中進行搜索的各種不同的Query類(如TermQuery、BooleanQuery等)和搜索結果集Hits類。

    7. store包 store包中是索引的存儲相關類,如Directory類定義了索引文件的存儲結構,FSDirectory是存儲在文件系統(即磁盤)中的索引存儲 類,RAMDirectory為存儲在內存中的索引存儲類,MmapDirectory為使用內存映射的索引存儲類。


  13. util包 util包中是公共工具類,例如時間和字符串之間的轉換工具。


    五、環境搭建

    使用Lucene3.6版本,到官網下載lucene-3.6.0.zip,解壓。
    需要用到的jar:
      \lucene-3.6.0\lucene-core-3.6.0.jar                      ------>      Lucene的核心包
      \lucene-3.6.0\contrib\analyzers\common\lucene-analyzers-3.6.0.jar    ------>      分詞器
      \lucene-3.6.0\contrib\highlighter\lucene-highlighter-3.6.0.jar                ------>      高亮關鍵詞使用
      \lucene-3.6.0\contrib\memory\lucene-memory-3.6.0.jar                     ------>      高亮關鍵詞使用

    Lucene3.6入門實例


    六、示例代碼

        package com.yulore.lucene;

    import java.io.File;
    import java.io.IOException;

    import org.apache.lucene.analysis.Analyzer;
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.document.Field;
    import org.apache.lucene.document.Field.Index;
    import org.apache.lucene.document.Field.Store;
    import org.apache.lucene.index.CorruptIndexException;
    import org.apache.lucene.index.IndexReader;
    import org.apache.lucene.index.IndexWriter;
    import org.apache.lucene.index.IndexWriterConfig;
    import org.apache.lucene.queryParser.MultiFieldQueryParser;
    import org.apache.lucene.queryParser.ParseException;
    import org.apache.lucene.queryParser.QueryParser;
    import org.apache.lucene.search.IndexSearcher;
    import org.apache.lucene.search.Query;
    import org.apache.lucene.search.ScoreDoc;
    import org.apache.lucene.store.Directory;
    import org.apache.lucene.store.FSDirectory;
    import org.apache.lucene.store.LockObtainFailedException;
    import org.apache.lucene.util.Version;
    import org.wltea.analyzer.lucene.IKAnalyzer;

    public class LuceneDemo02 {

     /** 
      * @param args 
      * @throws IOException  
      */  
     public static void main(String[] args) throws IOException {  
    
         createIndex();  
         queryLucene("Lucene");  
     }  
    
     /** 
      * 根據關鍵字搜索  
      * @param keyword 
      */  
     public static void queryLucene(String keyword){  
         try {  
             File path = new File("D://LuceneEx");  
             Directory mdDirectory = FSDirectory.open(path);  
             Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);  
    
             IndexReader reader = IndexReader.open(mdDirectory);  
    
             IndexSearcher searcher = new IndexSearcher(reader);  
    
    

    // Term term = new Term("title", keyword);
    // Query query = new TermQuery(term);

             String[] fields = { "title","tag"};  
             // (在多個Filed中搜索)  
             QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_36,  
                     fields, analyzer);  
             Query query = queryParser.parse(keyword);  
    
             long start = System.currentTimeMillis();      
    
             ScoreDoc[] docs = searcher.search(query, null, 3).scoreDocs;  
    
             for(int i=0;docs!=null && i<docs.length;i++){  
                 Document doc = searcher.doc(docs[i].doc);  
                 int id = Integer.parseInt(doc.get("id"));  
                 String title = doc.get("title");  
                 String author = doc.get("author");  
                 String tag = doc.get("tag");  
                 String reputation = doc.get("reputation");  
    
                 System.out.println(id+" "+title+" "+author+" "+tag+" "+reputation);  
             }  
    
             reader.close();  
             searcher.close();  
    
             long end = System.currentTimeMillis();  
             System.out.println("queryLucene耗時:"+(end-start)+"ms");  
    
         } catch (CorruptIndexException e) {  
             e.printStackTrace();  
         } catch (IOException e) {  
             e.printStackTrace();  
         } catch (ParseException e) {  
             e.printStackTrace();  
         }  
     }  
    
     /** 
      * 創建索引 
      */  
     private static void createIndex(){  
    
         try {  
    
             File path = new File("D://LuceneEx");  
             Directory mdDirectory = FSDirectory.open(path);  
    
              // 使用Lucene提供的分詞器    
    

    // Analyzer mAnalyzer = new StandardAnalyzer(Version.LUCENE_36);

             // 使用 商業分詞器    
             Analyzer mAnalyzer = new IKAnalyzer();    
             IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, mAnalyzer);  
    
             IndexWriter writer = new IndexWriter(mdDirectory, config);  
    
             long start = System.currentTimeMillis();  
    
             for(int i=0;i<10;i++){  
    
                 Document doc = new Document();  
    
                 Field id = new Field("id", "10000"+i, Store.YES, Index.ANALYZED);  
                 Field title = new Field("title", "Lucene開發入門"+i, Store.YES, Index.ANALYZED);  
                 Field author = new Field("author", "楊豐盛"+i, Store.YES, Index.ANALYZED);  
                 Field tag = new Field("tag", "Lucene、全文搜索"+i, Store.YES, Index.ANALYZED);  
                 Field reputation = new Field("reputation", "一本好書"+i, Store.YES, Index.ANALYZED);  
    
                 doc.add(id);  
                 doc.add(title);  
                 doc.add(author);  
                 doc.add(tag);  
                 doc.add(reputation);  
    
                 writer.addDocument(doc);  
             }  
    
             writer.close();  
    
             long end = System.currentTimeMillis();  
             System.out.println("createIndex耗時:"+(end-start)+"ms");  
    
         } catch (CorruptIndexException e) {  
             e.printStackTrace();  
         } catch (LockObtainFailedException e) {  
             e.printStackTrace();  
         } catch (IOException e) {  
             e.printStackTrace();  
         }  
     }  
    

    } </pre></div> </div> </div>


    參考http://www.cnblogs.com/bluepoint2009/archive/2012/09/25/introduction-to-lucene36.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!