现在的位置: 首页 > 综合 > 正文

为自己的系统搞个全文搜索

2013年03月15日 ⁄ 综合 ⁄ 共 6134字 ⁄ 字号 评论关闭

作者: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就可以了。
 

抱歉!评论已关闭.