使用Lucene2.3構建搜索引擎

Lucene不是一個完整的全文索引應用,而是是一個用Java寫的全文索引引擎工具包,它能夠方便的嵌入到各類應用中實現針對應用的全文索引/檢索功能。
Lucene的做者:Lucene的貢獻者Doug Cutting是一位資深全文索引/檢索專家,曾經是V-Twin搜索引擎(Apple的Copland操做系統的成就之一)的主要開發者,後在 Excite擔任高級系統架構設計師,目前從事於一些INTERNET底層架構的研究。他貢獻出的Lucene的目標是爲各類中小型應用程序加入全文檢索功能。
Lucene的發展歷程:早先發布在做者本身的[url]www.lucene.com[/url],後來發佈在SourceForge,2001年年末成爲APACHE基金會jakarta的一個子項目: [url]http://jakarta.apache.org/lucene/[/url]
已經有不少Java項目都使用了Lucene做爲其後臺的全文索引引擎
1、開始
     首先在Apache下載Lucene 2.3.0包,其中包含了核心jar和LuceneAPI文檔,解壓後,將 lucene-core-2.3.0.jar放在classpath中。
2、建立索引
     建立索引時須要指定存放索引的目錄(未來檢索時須要對這個目錄中的索引進行檢索),和文件的目錄(若是是對文件進行索引的話)代碼以下:
  
    public void crateIndex() throws Exception {
       File indexDir = new File( "D://luceneIndex" );
       // 存儲索引文件夾
       File dataDir = new File( "D://test" );
       // 須要檢索文件夾
Analyzer luceneAnalyzer = new PaodingAnalyzer();
// PaodingAnalyzer這個類是庖丁解牛中文分詞分析器類繼承了Lucene的 Analyzer接口,對於檢索中文分詞有很大幫助
       File[] dataFiles = dataDir.listFiles();
       boolean fileIsExist = false ;
       if (indexDir.listFiles(). length == 0)
           fileIsExist = true ;
       IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyzer , fileIsExist);
       // 第三個參數是一個布爾型的變量,若是爲 true 的話就表明建立一個新的索引,爲 false 的話就表明在原來索引的基礎上進行操做。
       long startTime = new Date().getTime();
       this .doIndex(dataFiles, indexWriter);
       indexWriter.optimize();//優化索引
       indexWriter.close();//關閉索引
       long endTime = new Date().getTime();
       System. out .println( "It takes " + (endTime - startTime)
              + " milliseconds to create index for the files in directory " + dataDir.getPath());
    {color:black}}

*    private{*} void doIndex(File[] dataFiles, IndexWriter indexWriter) throws Exception {
       for ( int i = 0; i < dataFiles. length ; i++) {
           if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith( ".html" )) {//索引全部html格式文件
              System. out .println( "Indexing file " + dataFiles[i].getCanonicalPath());
              Reader txtReader = new FileReader(dataFiles[i]);
              Document document = new Document();
              // Field.Store.YES 存儲 Field.Store.NO 不存儲
              // Field.Index.TOKENIZED 分詞 Field.Index.UN_TOKENIZED 不分詞
              document.add( new Field( "path" , dataFiles[i].getCanonicalPath(), Field.Store. YES , Field.Index. UN_TOKENIZED ));
              document.add( new Field( "filename" , dataFiles[i].getName(), Field.Store. YES , Field.Index. TOKENIZED ));
              // 另一個構造函數 , 接受一個 Reader 對象
              document.add( new Field( "contents" , txtReader));
              indexWriter.addDocument(document);
           {color:black}} else if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith( ".doc" )) {//索引全部word文件
              FileInputStream in = new FileInputStream(dataFiles[i]);// 得到文件流
              WordExtractor extractor = new WordExtractor(in);// 使用POI對word文件進行解析
              String str = extractor.getText();// 返回String
              Document document = new Document();//生成 Document對象,其中有3個 Field,分別是 path , filename, contents
              document.add( new Field( "path" , dataFiles[i].getCanonicalPath(), Field.Store. YES ,
                     Field.Index. UN_TOKENIZED ));
              document.add( new Field( "filename" , dataFiles[i].getName(), Field.Store. YES , Field.Index. TOKENIZED ));
              // 另一個構造函數 , 接受一個 Reader 對象
              document.add( new Field( "contents" , str, Field.Store. YES ,Field.Index. TOKENIZED ,
                                     Field.TermVector. WITH_POSITIONS_OFFSETS ));
              indexWriter.addDocument(document);
           {color:black}} else {
              if (dataFiles[i].isDirectory()) {
                  doIndex(dataFiles[i].listFiles(), indexWriter);//使用遞歸,繼續索引文件夾
              {color:black}}
           {color:black}}
       {color:black}}
    {color:black}}
從上面代碼中能夠看到對文件(或者說是數據)建立索引是一件很容易的事,首先肯定須要索引的文件夾(或者數據庫中的數據注:Lucene只接受數據,他不會區分數據的來源,也就是說無論是什麼你只要把它轉爲String格式的數據,Lucene就能建立索引),而後指定建立後索引存放的地方,咱們本身對數據處理後建立一個 Document對象這裏面你能夠本身定義放幾 Field,並定義 Field是否進行分詞什麼的,這樣索引就建立好了.
注:使用庖丁解牛中文分詞,須要將"庖丁"中的詞典(dic文件夾)放到classpath 中再把 paoding-analyzer.properties文件也放到classpath中 properties文件內容以下:
paoding.imports = {color}

ifexists:classpath:paoding-analysis-default.properties;{color}

ifexists:classpath:paoding-analysis-user.properties;{color}

ifexists:classpath:paoding-knives-user.properties
paoding.dic.home = classpath:dic
3、檢索
對於建立數據的索引咱們已經瞭解了,下面介紹一下,檢索數據, 檢索數據的時候咱們不用關心原始的數據或者文件,咱們只關心lucene生成的索引, 可是要使用當初生成索引時的同一個分析器進行分析索引.
  
public void searchIndex() throws Exception {
       String contents = " 項目 " ;//內容的關鍵字
       String filename = " 測試 " ;//文件名的關鍵字
       File indexDir = new File( "D:
luceneIndex"
);//存放索引的文件夾
       FSDirectory directory = FSDirectory. getDirectory (indexDir);
       Searcher searcher = new IndexSearcher(directory);
 
       QueryParser parserContents = new QueryParser( "contents" , luceneAnalyzer );
       QueryParser parserFilename = new QueryParser( "filename" , luceneAnalyzer );
       //使用同一個分析器 luceneAnalyzer分別生成兩個 QueryParser對象
       Query query1 = parserContents.parse(contents);
       Query query2 = parserFilename.parse(filename);
       BooleanQuery query = new BooleanQuery();
       query.add(query1, BooleanClause.Occur. MUST );
       query.add(query2, BooleanClause.Occur. MUST );
 
       SimpleHTMLFormatter formatter = new SimpleHTMLFormatter( "<span class=\"highlight\">" , "</span>" );
       Highlighter highlighter = new Highlighter(formatter, new QueryScorer(query));
       highlighter.setTextFragmenter( new SimpleFragmenter(60));
       //Lucene自帶的高亮功能,在Lucene發佈的bin中的 lucene-2.3.0\contrib\highlighter文件夾下 lucene-highlighter-2.3.0.jar 須要導入
       Hits hits = searcher.search(query);
           for ( int i=0;i<hits.length();i++){
              TokenStream tokenStream = luceneAnalyzer .tokenStream( "contents" , new StringReader(hits.doc.get( "contents" )));
              this . pageContext .getOut().println( "<font style='font-size:13px'><a href='" + hits.doc.get( "path" )  + "'><b>" +ELFuncUtil. setStyle (hits.doc.get( "filename" ), filename )+ "</b></a></font><br>" );
              String str = highlighter.getBestFragment(tokenStream,hits.doc.get( "contents" ) + "..." );
               this . pageContext .getOut().println( "<font style='font-size:12px'>" +str+ "</font>" );
              this . pageContext .getOut().println( "<br><hr><br>" );
           {color:black}}

   
{color:black}}

 
< style >
.highlight {
    background : yellow ;
    color : #CC0033 ;
{color:black}}

</
style >
這樣外界的訪問直接經過Lucene去檢索索引,不去觸及真正的文件,效率大大提升.頁面再加上一點修飾一個使用Lucene構建的搜索引擎就完成了.
相關文章
相關標籤/搜索