爲自己的系統搞個全文搜索

作者:gdsean(原作)

   在本文我又提到lucene了,在java業界,提到全文檢索,幾乎沒有什麼人不知道它。
用google搜索一下,滿世界都是有關資料。具有代表性的就是車東的“基於Java的全文索引引擎Lucene簡介”,
我要寫的也就只有最簡單的三板斧,再加上支持中文的ChineseAnalyzer以及按照時間排序的搜索結果排序方法。
這些都可以在其他地方找到相關資料,我只是把他們提出來,作爲lucence應用中經常遇到的麻煩解決辦法。
去年MSN上面有個朋友跟我提到希望用lucene構建個網站的全文檢索,我當時就覺得很簡單,直說沒問題沒問題,
不過他提到一個要求就是搜索結果要安裝時間排序,我查閱了些資料,發現lucene並不提供用戶自定義排序方式,
而只能按照自己相關性算法排序。後來我在車東的weblucene項目找到了IndexOrderSearcher。
解決了結果排序常規需求。
IndexOrderSearcher跟一般IndexSearch使用差不多,僅僅在構建對象的時候多加一個參數IndexOrderSearcher.ORDER_BY_DOCID_DESC
IndexOrderSearcher indexsearcher = new IndexOrderSearcher("/home/lucenetest/index",IndexOrderSearcher.ORDER_BY_DOCID_DESC);
新版本的lucene還提供了一個MultiFieldQueryParser,可以同時檢索多個字段,以前QueryParser比較麻煩。

    private  static  ChineseAnalyzer  chineseAnalyzer  =  new  ChineseAnalyzer();
    public  Hits  search(String  queryText){
                if  (queryText  ==  null){
                    return  null;
  }
  Query  query;
  try{
      query  =  MultiFieldQueryParser.parse(queryText,  new  String[]{"title"},chineseAnalyzer);
      return  indexsearcher.search(query);
  }catch(Exception  e){
      return  null;
  }
}
下面是構建索引,定時從數據庫取出數據索引,做完記錄完成時間,我是把時間寫入一個txt文件。
package  com.test.search;
import  org.apache.lucene.analysis.Analyzer;
import  org.apache.lucene.analysis.cn.*;
import  org.apache.lucene.analysis.standard.StandardAnalyzer;
import  org.apache.lucene.document.*;
import  org.apache.lucene.index.*;

import  java.io.*;
import  java.sql.*;
import  java.util.Date;

import  com.test.db.*;
import  com.test.utility.*;

/**
  *  Title:  SearchIndexer
  *  Description:  全文索引
  *  Copyright:      Copyright  (c)  2001
  *  Company:  test
  *  @author  Sean
  *  @version  1.0
  */
public  class  SearchIndexer  {
    private  String  indexPath  =  null;
    protected  Analyzer  analyzer  =  new  ChineseAnalyzer();

    public  SearchIndexer(String  s)  {
        this.indexPath  =  s;
    }
    /**
      *  索引某日期以前的所有文檔
      *  @param  fromdate
      *  @return
      */
    public  final  void  updateIndex(String  fromdate)  {
        Connection  conn  =  DbUtil.getCon();
        IndexWriter  indexWriter  =  null;
        try  {
            indexWriter  =  getWriter(false);
          //索引發布系統內部文件
                PreparedStatement  pstm  =  conn.prepareStatement(
                        "select  title,body,creationtime  from  document  where  creationtime  >  '"  +  fromdate  +
                        "'  order  by  creationtime");
                ResultSet  rs  =  pstm.executeQuery();
                while  (rs.next())  {
                    String  creationtime  =  rs.getString("creationtime");
                    String  title  =  rs.getString("title");
                    String  body  =  rs.getString("body");

                   
                    if  (title  ==  null  ||  body  ==  null)  {
                        continue;
                    }
                    try  {
                        addDocsToIndex(title,body,  creationtime,indexWriter);
                    }
                    catch  (Exception  ex)  {
                        ex.printStackTrace();
                    }
              }
            indexWriter.optimize();
        }
        catch  (Exception  ex)  {
            ex.printStackTrace();
        }
        finally  {
            try  {
                indexWriter.close();
                conn.close();
            }
            catch  (Exception  e)  {
                e.printStackTrace();
            }
        }
    }
    /**
      *  檢查索引文件是否存在
      *  @param  s
      *  @return  索引是否存在
      */
    private  boolean  indexExists(String  s)  {
        File  file  =  new  File(s  +  File.separator  +  "segments");
        return  file.exists();
    }
    /**
      *  增加一組索引
      *  @param  title
      *  @param  body
      *  @param  creationtime
      *  @param  indexwriter
      *  @return
      */
    private  final  void  addNewsToIndex(String  docid,  String  url,String  title,  String  body,
                                                                            String  ptime,  IndexWriter  indexwriter)  throws
            IOException  {
        if  (indexwriter  ==  null)  {
            return;
        }
        else  {
            try  {
                Document  document  =  new  Document();
                document.add(Field.Text("title",  title));
                document.add(Field.Text("body",  body));
                document.add(new  Field("creationtime",  creationtime,  true,  true,  false));
                indexwriter.addDocument(document);
            }
            catch  (Exception  ex)  {
        ex.printStackTrace();
            }
            return;
        }
    }
    /**
      *  取得IndexWriter
      *  @param  flag  是否新建索引
      *  @return  IndexWriter
      */
    private  IndexWriter  getWriter(boolean  flag)  throws  IOException  {
        String  s  =  indexPath;
        if  (s  ==  null)  {
            throw  new  IOException("索引文件路徑設置錯誤.");
        }
        indexPath  =  s  +  File.separator  +  "search";
        IndexWriter  indexwriter  =  null;
        if  (flag)  {
            try  {
                indexwriter  =  new  IndexWriter(indexPath,  analyzer,  true);
            }
            catch  (Exception  exception)  {
                System.err.println("ERROR:  Failed  to  create  a  new  index  writer.");
                exception.printStackTrace();
            }
        }
        else  {
            if  (indexExists(indexPath))  {
                try  {
                    indexwriter  =  new  IndexWriter(indexPath,  analyzer,  false);
                }
                catch  (Exception  exception1)  {
                    System.err.println("ERROR:  Failed  to  open  an  index  writer.");
                    exception1.printStackTrace();
                }
            }
            else  {
                try  {
                    indexwriter  =  new  IndexWriter(indexPath,  analyzer,  true);
                }
                catch  (Exception  exception2)  {
                    System.err.println("ERROR:  Failed  to  create  a  new  index  writer.");
                    exception2.printStackTrace();
                }
            }
        }
        return  indexwriter;
    }

    public  static  void  main(String[]  args)  {
        String  lastUpdate  =  "/home/lucenetest/lastUpdate.txt";
        SearchIndexer  searchIndexer  =  new  SearchIndexer("/home/lucenetest/index");
        //取出上次更新時間
        String  str  =  Util.readTxtFile(lastUpdate);
        if(str==null  ||  str.length()==0){
            str  =  new  java.util.Date().toString();
        }
        searchIndexer.updateIndex(str);
        //寫入當前時間
        Util.writeTxtFile(lastUpdate,new  java.util.Date(),false);
    }
}

寫個cmd或者sh在相應操作系統下面定時執行SearchIndexer就可以了。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章