1、lucene入門(lucene筆記)

一、概述

lucene是一個全文搜索引擎,在全文索引工具中,都是由這樣的但部分組成:

  • 1、索引部分
  • 2、分詞部分
  • 3、搜索部分

二、入門程序

2.1 入門程序

這里我們需要導入lucenejar包,注意:這里使用的是3.5.0版本,lucene的各個版本差異較大。
下面看入門程序,看lucene如何創建索引和搜索索引(工程lucene01):
HelloLucene.java

package cn.lucene.test;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
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.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.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

public class HelloLucene {
    
    //建立索引
    public void index(){
        IndexWriter writer = null;
        try {
            //1、創建Directory
            //Directory directory = new RAMDirectory();//索引是建立在內存中的
            Directory directory = FSDirectory.open(new File("E:/myeclipse/Lucene/index"));//創建在硬盤上
            
            //2、創建IndexWriter
            IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
            writer = new IndexWriter(directory, iwc);
            
            //3、創建Document對象
            Document doc = null; 
                    
            //4、為Document添加Field,是Document的一個子元素
            File file = new File("E:/myeclipse/Lucene/somefile");
            for(File f : file.listFiles()){
                doc = new Document();
                doc.add(new Field("content", new FileReader(f)));
                doc.add(new Field("filename", f.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                doc.add(new Field("path", f.getAbsolutePath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
                //5、通過IndexWriter添加文檔到索引中
                writer.addDocument(doc);
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (LockObtainFailedException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(writer != null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //搜索
    public void search(){
        Directory directory;
        try {
            //1、創建Directory
            directory = FSDirectory.open(new File("E:/myeclipse/Lucene/index"));
            
            //2、創建IndexReader
            IndexReader reader = IndexReader.open(directory);
            //3、根據IndexReader創建IndexSearcher
            IndexSearcher searcher = new IndexSearcher(reader);
            //4、創建搜索的Query
            //創建QueryParser來確定要搜索文件的內容,第二個參數表示搜索的域
            QueryParser parser = new QueryParser(Version.LUCENE_35, "content", new StandardAnalyzer(Version.LUCENE_35));
            //創建Query,表示搜索域為content中包含java的文檔
            Query query = parser.parse("java");
            //5、根據searcher搜索并且返回TopDocs
            TopDocs tdoc = searcher.search(query, 10);//只會顯示10條內容
            
            //6、根據TopDocs獲取ScoreDoc對象
            ScoreDoc sdocs[] = tdoc.scoreDocs;
            for(ScoreDoc s : sdocs){
                //7、根據searcher行業ScoreDoc獲取具體的Document對象
                Document document = searcher.doc(s.doc);
                //8、根據Document對象獲取所需要的值
                System.out.println(document.get("filename") + "[" + document.get("path") + "]");
            }
            //9、關閉reader
            reader.close(); 
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}

說明:這里我們存儲的文檔放在E:/myeclipse/Lucene/somefile中,創建的搜索我們放在E:/myeclipse/Lucene/index中,這里方法index()是創建文檔索引的方法,而search()是搜索文檔索引的方法。

2.2 測試

TestLucene.java

package cn.lucene.test;
import org.junit.Test;
public class TestLucene {
    
    @Test
    public void testIndex(){
        HelloLucene hLucene = new HelloLucene();
        hLucene.index();
    }
    
    @Test
    public void testSearch(){
        HelloLucene hLucene = new HelloLucene();
        hLucene.search();
    }
}

說明:這里我們在創建文檔之后再次創建生成的索引不會覆蓋,而是會增加,這是因為lucene索引是一種增量索引,每次生成索引都不會將前面生成的索引刪除,而是添加,于是每次搜索出來的結果會有重復。這里我們搜索關鍵字為java,會打印出相關的文件路徑,這里我們先不深究程序的具體實現。

三、相關概念

3.1 建立索引時最重要的幾個術語

  • Document:一個要進行索引的單元,相當于數據庫的一行紀錄,任何想要被索引的數據,都必須轉化為Document對象存放。

  • FieldDocument中的一個字段,相當于數據庫中的Column ,Fieldlucene比較多概念一個術語。

  • IndexWriter:負責將Document寫入索引文件。通常情況下,IndexWriter的構造函數包括了以下3個參數:索引存放的路徑,分析器和是否重新創建索引。特別注意的一點,當IndexWriter執行完addDocument方法后,一定要記得調用自身的close方法來關閉它。只有在調用了close方法后,索引器才會將存放在內在中的所有內容寫入磁盤并關閉輸出流。

  • Analyzer:分析器,主要用于文本分詞(可以這樣理解,就是將一段話分成單個的詞語,然后為單個的詞語建立標識,便于搜索,就像一個超鏈接一樣)。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。

  • Directory:索引存放的位置。lucene提供了兩種索引存放的位置,一種是磁盤,一種是內存。一般情況將索引放在磁盤上;相應地lucene提供了FSDirectoryRAMDirectory兩個類。

  • 段:SegmentLucene索引文件的最基本的一個單位。Lucene說到底就是不斷加入新的Segment,然后按一定的規則算法合并不同的Segment以合成新的Segment。我們在上面測試時從建立的索引文件中就可以看出有如

    1

    圖中使用0,1標號表示的就是段,而這里我們可以看到每次創建索引都是增加而不是覆蓋。

  • 最后lucene建立索引的過程就是將待索引的對象轉化為LuceneDocument對象,使用IndexWriter將其寫入lucene 自定義格式的索引文件中。待索引的對象可以來自文件、數據庫等任意途徑,用戶自行編碼遍歷目錄讀取文件或者查詢數據庫表取得ResultSet,LuceneAPI只負責和字符串打交道。

3.2 存儲域選項

存儲域選項有Field.Store.YESField.Store.NO,設置為YES表示把這個域中的內容完全存儲到文件中,方便進行文本的還原,設置為NO表示不把這個域中的內容完全存儲到文件中,但是可以被索引,此時內容無法完全還原。比如一篇文章,我們可以建立文章的索引(此索引就是用來搜索這篇文章的一個標簽),但是我們可以不將整片文章內容全部存儲下來,但是這樣我們雖然能搜索到這篇文章,但是卻不能將其還原。

3.3 索引域選項:

  • Field.Index.ANALYZED:進行分詞和索引,適用于標題、內容等。
  • Field.Index. ANALYZED_NO_NORMS:進行分詞但是不存儲norms信息,這個norms中包括創建索引的時間和權值等信息
  • Field.Index. NOT_ANALYZED:進行索引,但是不進行分詞,如身份證號、姓名、ID等,試用于精確索引
  • Field.Index. NOT_ANALYZED_NO_NORMS:即不進行分詞也不存儲norms信息
  • Field.Index.NO:不進行索引

3.4 最佳實踐

域選項 存儲與否 最佳實踐
NOT_ANALYZED_NO_NORMS YES 標識符(主鍵、文件名),電話號碼,身份證號,姓名,日期
ANALYZED YES 文檔標題和摘要
ANALYZED NO 文檔正文
NO YES 文檔類型,數據庫主鍵(不進行索引)
NOT_ANALYZED NO 隱藏關鍵字
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容