敬的世界

          常用鏈接

          統計

          最新評論

          用Lucene 實現全文檢索

          來源:http://bbs.bc-cn.net/thread-180603-1-1.html


          在本文我又提到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就可以了。

          posted on 2009-01-28 23:56 picture talk 閱讀(177) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 喜德县| 平定县| 安乡县| 漾濞| 东平县| 茂名市| 额尔古纳市| 鹰潭市| 宾阳县| 银川市| 沾化县| 都江堰市| 乌海市| 多伦县| 莱州市| 安陆市| 浠水县| 嫩江县| 五台县| 麦盖提县| 霸州市| 嘉黎县| 咸丰县| 台北县| 中西区| 吴忠市| 柳州市| 玉屏| 和静县| 驻马店市| 湖州市| 宝鸡市| 依安县| 儋州市| 泾源县| 剑川县| 苏尼特左旗| 南阳市| 新野县| 连城县| 文登市|