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

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

    本文Lucene使用的版本爲4.0.0數據庫

1.    建立索引。工具

索引建立原理大體分爲如下幾步:spa

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

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

  • 索引,對處理後的詞元創建詞典。例如,詞‘中國’出如今ID257的文檔中,出現頻率分別爲153次。對象

具體實現以下:排序

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

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

    而後經過IndexWriter對象來建立和維護索引。Analyzer爲索引分詞器,主要是對獲取的文本進行分詞操做。因爲Lucene是由外國人開發的,因此自己對中文的分詞效果不是很好。因爲中文不像英文那樣,詞與詞之間有明顯的分隔符(英文通常以空格區分),因此中文分詞在實現上就比英文分詞複雜困難的多,並且歧義識別和新詞識別一直是中文分詞中的難點。token

    迴歸正題,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();
相關文章
相關標籤/搜索