kingpub

          海內(nèi)存知己,博客若比鄰

           

          為自己的系統(tǒng)搞個(gè)全文搜索

          在本文我又提到lucene了,在java業(yè)界,提到全文檢索,幾乎沒(méi)有什么人不知道它。
          用google搜索一下,滿(mǎn)世界都是有關(guān)資料。具有代表性的就是車(chē)東的“基于Java的全文索引引擎Lucene簡(jiǎn)介”,
          我要寫(xiě)的也就只有最簡(jiǎn)單的三板斧,再加上支持中文的ChineseAnalyzer以及按照時(shí)間排序的搜索結(jié)果排序方法。
          這些都可以在其他地方找到相關(guān)資料,我只是把他們提出來(lái),作為lucence應(yīng)用中經(jīng)常遇到的麻煩解決辦法。
          去年MSN上面有個(gè)朋友跟我提到希望用lucene構(gòu)建個(gè)網(wǎng)站的全文檢索,我當(dāng)時(shí)就覺(jué)得很簡(jiǎn)單,直說(shuō)沒(méi)問(wèn)題沒(méi)問(wèn)題,
          不過(guò)他提到一個(gè)要求就是搜索結(jié)果要安裝時(shí)間排序,我查閱了些資料,發(fā)現(xiàn)lucene并不提供用戶(hù)自定義排序方式,
          而只能按照自己相關(guān)性算法排序。后來(lái)我在車(chē)東的weblucene項(xiàng)目找到了IndexOrderSearcher。
          解決了結(jié)果排序常規(guī)需求。
          IndexOrderSearcher跟一般IndexSearch使用差不多,僅僅在構(gòu)建對(duì)象的時(shí)候多加一個(gè)參數(shù)IndexOrderSearcher.ORDER_BY_DOCID_DESC
          IndexOrderSearcher indexsearcher = new IndexOrderSearcher("/home/lucenetest/index",IndexOrderSearcher.ORDER_BY_DOCID_DESC);
          新版本的lucene還提供了一個(gè)MultiFieldQueryParser,可以同時(shí)檢索多個(gè)字段,以前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;
          }
          }
          下面是構(gòu)建索引,定時(shí)從數(shù)據(jù)庫(kù)取出數(shù)據(jù)索引,做完記錄完成時(shí)間,我是把時(shí)間寫(xiě)入一個(gè)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);
          //索引發(fā)布系統(tǒng)內(nèi)部文件
          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("索引文件路徑設(shè)置錯(cuò)誤.");
          }
          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");
          //取出上次更新時(shí)間
          String str = Util.readTxtFile(lastUpdate);
          if(str==null || str.length()==0){
          str = new java.util.Date().toString();
          }
          searchIndexer.updateIndex(str);
          //寫(xiě)入當(dāng)前時(shí)間
          Util.writeTxtFile(lastUpdate,new java.util.Date(),false);
          }
          }
          寫(xiě)個(gè)cmd或者sh在相應(yīng)操作系統(tǒng)下面定時(shí)執(zhí)行SearchIndexer就可以了。

          posted on 2006-08-17 18:27 xiaofeng 閱讀(210) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): weblucene

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(2)

          隨筆分類(lèi)

          隨筆檔案

          文章分類(lèi)

          文章檔案

          收藏夾

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 泸西县| 阿坝县| 米泉市| 三门峡市| 永寿县| 崇文区| 莱西市| 霍林郭勒市| 定西市| 穆棱市| 尼玛县| 高雄市| 沽源县| 虞城县| 青神县| 黎平县| 修文县| 儋州市| 武宣县| 襄城县| 德清县| 新民市| 阿鲁科尔沁旗| 周至县| 武山县| 灵丘县| 鹤岗市| 常州市| 融水| 清镇市| 武夷山市| 大兴区| 伊通| 通山县| 金昌市| 晋中市| 舞阳县| 小金县| 山丹县| 哈密市| 桦甸市|