kingpub

          海內存知己,博客若比鄰

           

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

          在本文我又提到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 2006-08-17 18:27 xiaofeng 閱讀(210) 評論(0)  編輯  收藏 所屬分類: weblucene

          導航

          統計

          常用鏈接

          留言簿(2)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          收藏夾

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 托里县| 海丰县| 西藏| 禄丰县| 县级市| 云梦县| 东城区| 永康市| 平顶山市| 无极县| 潼南县| 申扎县| 镇康县| 三台县| 凤翔县| 嵩明县| 大方县| 荔浦县| 上杭县| 松江区| 阿拉尔市| 林周县| 九江县| 太原市| 邵阳县| 绥化市| 堆龙德庆县| 桂东县| 永济市| 新化县| 馆陶县| 舞钢市| 西吉县| 白城市| 当阳市| 旺苍县| 开江县| 临潭县| 金寨县| 南陵县| 盱眙县|