Lucene小記(入門篇),索引創建、更新、刪除、查找等操作

jopen 11年前發布 | 89K 次閱讀 Lucene 搜索引擎

    雖然使用Lucene已經有一段時間了,但是仍不敢妄加評論Lucene的好與壞,畢竟目前接觸的全文索引技術只有Lucene。而且Lucene并不是真正意義上的引擎,只算的上是Java開發的全文索引工具包。與傳統的數據庫查詢對比,全文索引技術更具有優勢。Lucene不僅可以對磁盤文件進行索引,也可以對數據庫記錄進行索引,并且支持的索引文件格式多種多樣(結合其他的文本處理工具)。言歸正傳,本文將為讀者具體講解Lucene的基本使用,入門級。

    本文Lucene使用的版本為4.0.0

1.    創建索引。

索引創建原理大致分為以下幾步:

  • 分詞,將原文檔傳給分詞組件進行分詞,得到詞元。

  • 詞元處理,將詞元傳給語言處理組件進行一些語言處理,例如:變小寫,轉詞根。

  • 索引,對處理后的詞元建立詞典。例如,詞‘中國’出現在ID257的文檔中,出現頻率分別為153次。

具體實現如下:

    創建索引時需要兩個目錄,一個是索引文件的存放目錄(indexPath),一個是待索引的文件目錄(docsPath)。在創建索引時,我們首先要加載或創建索引目錄。常用的目錄創建方式有兩種:

  • 通過RAMDirectory()類創建一個內存目錄,內存目錄優點是速度快,缺點是程序退出后索引目錄數據就會丟失。
 RAMDirectory directory = new RAMDirectory();
  • 通過FSDirectory類加載一個文件目錄,該方式創建的索引數據保存在磁盤上,不會因為程序的退出而消失。下文都是針對FSDirectory方式來講解Lucene的基本使用。
Directory dir = FSDirectory.open(new File(indexPath)); 

    然后通過IndexWriter對象來創建和維護索引。Analyzer為索引分詞器,主要是對獲取的文本進行分詞操作。由于Lucene是由外國人開發的,所以本身對中文的分詞效果不是很好。由于中文不像英文那樣,詞與詞之間有明顯的分隔符(英文一般以空格區分),所以中文分詞在實現上就比英文分詞復雜困難的多,而且歧義識別和新詞識別一直是中文分詞中的難點。

    回歸正題,IndexWriterConfig對象用來設置IndexWriter一些初始配置,一旦IndexWriter對象創建完成,改變IndexWriterConfig的配置對已創建的IndexWriter對象不會產生影響。

Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_40, analyzer);                 
iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);//設置索引維護的方式
iwc.setRAMBufferSizeMB(256.0);//設置用來緩沖文檔的RAM大小
IndexWriter writer = new IndexWriter(dir, iwc); 

    接下來需要創建Document文檔,并通過IndexWriter對象將文檔添加到索引庫中。Document文檔可以是一個HTML頁面,一篇文本文檔,一封電子郵件。一個Document可以包含多個FieldField代表文檔的屬性。此處file為文件對象。

Document doc = new Document();         
doc.add(new StringField("path", file.getPath(), Field.Store.YES));
doc.add(new TextField("filename", file.getName(), Field.Store.YES)); 

注意:StringField被索引不被分詞,整個值被看作為一個單獨的token而被索引。

     TextField既被索引又被分詞,但是沒有詞向量。

    Filed類型還包含LongFieldDoubleFieldIntFiled等,具體的含義請參考官方API

    最后需要將文檔添加到索引庫中。

writer.addDocument(doc);
writer.close(); 

2.    檢索索引。

檢索索引的原理大致如下:

  • 對查詢語句進行詞法分析、語法分析和語言處理。詞法分析主要是識別單詞和關鍵字。語法分析主要是根據查詢語句的語法規則來形成一顆語法樹。語言處理與索引建立過程中語言處理幾乎相同。

  • 搜索索引,得到符合語法樹的文檔

  • 根據得到的文檔和查詢語句的相關性,對結果進行排序。

具體實現如下:

    檢索索引首先要讀取索引文檔,并建立IndexSearch對象。

IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(indexPath)));
IndexSearcher searcher = new IndexSearcher(reader); 

    然后需要對查詢語句進行分析,Lucene通過Query接口實現類來對查詢條件進行分析。Lucene支持單Filed查詢、多Field查詢、邏輯組合查詢、模糊查詢、范圍查詢、通配符查詢等。各種查詢方式的具體實現本文暫時不討論。

  1. 單字段查詢。

Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
QueryParser queryParser = new QueryParser(Version.LUCENE_40, " filename",analyzer) ;
queryParser.setDefaultOperator(QueryParser.OR_OPERATOR);//設置默認邏輯‘或’查詢
Query query = queryParser.parse(condition); 
  1. 多字段查詢

String[] fields = new String[]{"filename"," path "};
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
//MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(Version.LUCENE_40, fields, analyzer);
//Query query = multiFieldQueryParser.parse(condition);
BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
                                                     BooleanClause.Occur.MUST};
Query query = MultiFieldQueryParser.parse(Version.LUCENE_40, condition, fields, flags, analyzer); 

    接下來,通過IndexSearcher對象進行查找。對查詢出來的結果可以進行高亮顯示關鍵字,取摘要等處理。    

    TopDocs results = searcher.search(query,10);
    ScoreDoc[] hits = results.scoreDocs;
    for(ScoreDoc hit:hits){
        Document doc = searcher.doc(hit.doc);
        SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
        Highlighter highlighter = new Highlighter(formatter, new QueryScorer(query));
        Fragmenter fragmenter =new SimpleFragmenter(80);
        highlighter.setTextFragmenter(fragmenter);
        Information information = new Information();
        information.setId(hit.doc);                                 
        information.setPath(doc.get("path"));
        if(highlighter.getBestFragment(analyzer, "filename", doc.get("filename"))==null){
            information.setFileName(doc.get("filename"));
        }else{
            information.setFileName(highlighter.getBestFragment(analyzer, "filename", doc.get("filename")));
        }
        informations.add(information);
    } 

3.    更新索引。

Lucene索引的更新為調用IndexWriterupdateDocument方法,該方法接受兩個參數,第一個Term詞向量,第二個為新增的文檔,可以是單個文檔,也可以是批量文檔。Lucene會先根據Term刪除索引庫中原有的文檔,再向索引庫中添加新的documentTerm的第一參數表示要在文檔的哪個Field上查找,第二個代表查詢關鍵字。

 writer.updateDocument(new Term("path", file.getPath()), doc); 

4.    刪除索引。

Lucene索引的刪除的可以根據Query對象來刪除,也可以根據Term來刪除,也可以一次刪除全部索引。

//根據Term刪除
writer.deleteDocuments(new Term("path", file.getPath()));
//刪除全部索引
writer.deleteAll(); 

 

 

 


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