用户名: 密 码:
您现在的位置:首页 >> SEO开发技巧 >> 内容

Lucene搜索引擎扩展

时间:2009-10-25 17:28:02 点击:3706

  核心提示:Lucene是什么,干什么用的我就不再一一说了,只是在很多时候可能我们会需要用到,因为基本上应用系统都会有查询的功能,比如模糊查询等,对于基本的知识我不多说,大家可以去搜索别的文章看,下面我列出我扩展的及各类供大家看看,有不足之处望大家提出来,共同学习。 首先列出所需Jar包: lucene-cor...
Lucene是什么,干什么用的我就不再一一说了,只是在很多时候可能我们会需要用到,因为基本上应用系统都会有查询的功能,比如模糊查询等,对于基本的知识我不多说,大家可以去搜索别的文章看,下面我列出我扩展的及各类供大家看看,有不足之处望大家提出来,共同学习。
首先列出所需Jar包:
lucene-core-2.4.1.jar
lucene-highlighter-2.4.1.jar
log4j-1.2.14.jar
commons-beanutils-1.5.jar
commons-collections-2.1.1.jar
commons-logging-1.0.4.jar
代码:
DocumentFactory.java
Java代码 复制代码
  1. /*  
  2.  * @(#)Documents.java 2009-10-09   
  3.  */  
  4. package com.ordinov.lucene;   
  5.   
  6. import java.lang.reflect.InvocationTargetException;   
  7. import java.util.ArrayList;   
  8. import java.util.List;   
  9.   
  10. import org.apache.commons.beanutils.BeanUtils;   
  11. import org.apache.lucene.document.Document;   
  12. import org.apache.lucene.document.Field;   
  13.   
  14. /**  
  15.  * 索引文件内容创建类  
  16.  *   
  17.  * @author weich  
  18.  * @Date 2009-10-09  
  19.  *  
  20.  */  
  21. public class DocumentFactory {   
  22.        
  23.   
  24.     /**  
  25.      * 获取数据内容用来建立索引(针对单个对象)<br>  
  26.      * 默认Bean类中第一个属性处理方式为:建立索引但是不使用分词  
  27.      *   
  28.      * @param <T> 实体Bean对象  
  29.      * @param fields Bean对象的Field属性  
  30.      * @param obj 需要转换的Bean对象  
  31.      * @return   
  32.      * @throws java.io.FileNotFoundException  
  33.      * @throws IllegalAccessException  
  34.      * @throws InvocationTargetException  
  35.      * @throws NoSuchMethodException  
  36.      */  
  37.     public static <T> Document getDataDocument(java.lang.reflect.Field[] fields,T obj)throws java.io.FileNotFoundException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {   
  38.            
  39.         Document doc = new Document();   
  40.         doc.add(new Field(fields[0].getName(),BeanUtils.getProperty(obj, fields[0].getName()), Field.Store.YES, Field.Index.NOT_ANALYZED));   
  41.         for(int i =1; i < fields.length; i++){   
  42.             doc.add(new Field(fields[i].getName(),BeanUtils.getProperty(obj, fields[i].getName()), Field.Store.YES,  Field.Index.ANALYZED));   
  43.         }   
  44.         return doc;   
  45.      }   
  46.   
  47.     /**  
  48.      * 获取数据内容用来建立索引(针对多个对象)<br>  
  49.      * 默认Bean类中第一个属性处理方式为:建立索引但是不使用分词  
  50.      *   
  51.      * @param <T> 实体Bean对象  
  52.      * @param cls Bean类的Class对象  
  53.      * @param objs 需要转换的Bean对象数组  
  54.      * @return  
  55.      * @throws java.io.FileNotFoundException  
  56.      * @throws IllegalAccessException  
  57.      * @throws InvocationTargetException  
  58.      * @throws NoSuchMethodException  
  59.      */  
  60.     public static <T> Document[] getDataDocuments(Class<T> cls,T[] objs)throws java.io.FileNotFoundException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {   
  61.            
  62.         List<Document> docs= new ArrayList<Document>();      
  63.         java.lang.reflect.Field[] fields = cls.getDeclaredFields();   
  64.         for(T obj : objs)   
  65.             docs.add(getDataDocument(fields,obj));   
  66.         return docs.toArray(new Document[0]);   
  67.      }   
  68. }  

IndexManger.java
Java代码 复制代码
  1. /*  
  2.  * @(#)IndexFactory.java 2009-10-09   
  3.  */  
  4. package com.ordinov.lucene;   
  5.   
  6. import java.io.File;   
  7. import java.io.FileNotFoundException;   
  8. import java.io.IOException;   
  9. import java.lang.reflect.InvocationTargetException;   
  10.   
  11. import org.apache.log4j.Logger;   
  12. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  13. import org.apache.lucene.document.Document;   
  14. import org.apache.lucene.index.CorruptIndexException;   
  15. import org.apache.lucene.index.IndexWriter;   
  16. import org.apache.lucene.store.LockObtainFailedException;   
  17.   
  18. /**  
  19.  * 检索工厂类<br>  
  20.  * 主要负责索引的创建工作,提供检索类调用。  
  21.  *   
  22.  * @author weich  
  23.  * @Date 2009-10-09  
  24.  *   
  25.  */  
  26. public class IndexManger {   
  27.   
  28.     /** 日志记录器 */  
  29.     static private Logger logger = Logger.getLogger(IndexManger.class);   
  30.     /** 分词器 StandardAnalyzer 按字分词,支持中文分词 */  
  31.     private StandardAnalyzer analyzer = null;   
  32.     /** 索引写出类对象主要负责索引的创建 */  
  33.     private IndexWriter writer = null;   
  34.     /** 是否新建索引 true-新建索引,false-追加索引。默认为true */  
  35.     private boolean isNewCreat = true;   
  36.     /** 索引文件保存路径 */  
  37.     private String indexPath= null;   
  38.     /** 对搜索结果内容进行过滤,可以禁止搜索部分词汇 */  
  39.     private String [] stopStrs = {};   
  40.   
  41.     /**  
  42.      * IndexFactory构造器 <br>  
  43.      * 初始化创建索引文件时必须的一些属性  
  44.      *   
  45.      * @throws IOException   
  46.      * @throws LockObtainFailedException   
  47.      * @throws CorruptIndexException   
  48.      *   
  49.      */  
  50.     public IndexManger() throws CorruptIndexException, LockObtainFailedException, IOException{   
  51.   
  52.         /* 初始化所需对象实例 */  
  53.         init();   
  54.     }   
  55.   
  56.     /**  
  57.      * IndexFactory 构造器<br>  
  58.      * 初始化创建索引文件时必须的一些属性  
  59.      *   
  60.      * @param indexPath 索引文件保存路径  
  61.      * @param stopStrs 搜索结果过滤词汇  
  62.      * @param isCreat 是否新创建索引  
  63.      *   
  64.      * @throws CorruptIndexException  
  65.      * @throws LockObtainFailedException  
  66.      * @throws IOException  
  67.      */  
  68.     public IndexManger(String indexPath,String [] stopStrs,boolean isCreat) throws CorruptIndexException, LockObtainFailedException, IOException{   
  69.   
  70.         if(indexPath != null && !"".equals(indexPath)){   
  71.             this.indexPath=indexPath;   
  72.         }   
  73.         if(stopStrs != null && stopStrs.length > 0){   
  74.             this.stopStrs=stopStrs;   
  75.         }   
  76.         this.isNewCreat=isCreat;   
  77.         /* 初始化所需对象实例 */  
  78.         init();   
  79.     }   
  80.   
  81.     /**  
  82.      * 初始化对象实例<br>  
  83.      * 创建分词器对象以及索引写出对象  
  84.      *   
  85.      * @throws CorruptIndexException  
  86.      * @throws LockObtainFailedException  
  87.      * @throws IOException  
  88.      */  
  89.     private void init() throws CorruptIndexException, LockObtainFailedException, IOException{   
  90.   
  91.         analyzer=new StandardAnalyzer(stopStrs);   
  92.         writer= new IndexWriter(new File(indexPath),analyzer,this.isNewCreat,IndexWriter.MaxFieldLength.UNLIMITED);   
  93.     }   
  94.   
  95.     /**  
  96.      * 创建索引文件  
  97.      *   
  98.      * @param docs 需要添加到  
  99.      *   
  100.      * @throws IOException   
  101.      * @throws CorruptIndexException   
  102.      */  
  103.     private void addDocs(Document[] docs) throws CorruptIndexException, IOException{   
  104.   
  105.         if(docs != null && docs.length > 0){   
  106.             for(int i=0; i<docs.length;i++){   
  107.                 /* 向IndexWriter对象中加入Document记录 */  
  108.                 this.addDoc(docs[i]);   
  109.             }   
  110.         }   
  111.     }   
  112.   
  113.     /**  
  114.      * 向IndexWriter对象中添加一条Document记录   
  115.      *   
  116.      * @param doc 需要在  
  117.      * @throws IOException   
  118.      * @throws CorruptIndexException   
  119.      */  
  120.     private void addDoc(Document doc) throws CorruptIndexException, IOException{   
  121.   
  122.         /* 向IndexWriter对象中加入Document记录 */  
  123.         writer.addDocument(doc);   
  124.     }   
  125.   
  126.     /**  
  127.      * 在磁盘上创建索引文件,并优化合并,最后会关闭IndexWriter对象  
  128.      *   
  129.      * @throws IOException   
  130.      * @throws CorruptIndexException   
  131.      */  
  132.     private void close() throws CorruptIndexException, IOException{   
  133.   
  134.         logger.debug("关闭索引写出对象实例...");   
  135.         /* 将缓存中索引文件写入磁盘,并优化合并。 */  
  136.         writer.optimize();    
  137.         /* 关闭IndexWriter对象 */  
  138.         writer.close();   
  139.     }   
  140.   
  141.     /**  
  142.      * 创建索引根据用户指定的类型  
  143.      *   
  144.      * @param <T>  
  145.      * @param cls Bean类的Class对象  
  146.      * @param objs Bean对象数组  
  147.      * @throws CorruptIndexException  
  148.      * @throws FileNotFoundException  
  149.      * @throws IOException  
  150.      * @throws IllegalAccessException  
  151.      * @throws InvocationTargetException  
  152.      * @throws NoSuchMethodException  
  153.      */  
  154.     public <T> void createIndex(Class<T> cls,T[] objs) throws CorruptIndexException, FileNotFoundException, IOException, IllegalAccessException, InvocationTargetException, NoSuchMethodException{   
  155.   
  156.         this.addDocs(DocumentFactory.getDataDocuments(cls, objs));   
  157.         /* 关闭索引写出对象 */  
  158.         this.close();   
  159.     }   
  160. }  

SerchIndex.java
Java代码 复制代码
  1. package com.ordinov.lucene;   
  2.   
  3. import java.io.StringReader;   
  4. import java.lang.reflect.Field;   
  5. import java.util.ArrayList;   
  6. import java.util.List;   
  7.   
  8. import org.apache.commons.beanutils.BeanUtils;   
  9. import org.apache.lucene.analysis.Analyzer;   
  10. import org.apache.lucene.analysis.TokenStream;   
  11. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  12. import org.apache.lucene.document.Document;   
  13. import org.apache.lucene.index.IndexReader;   
  14. import org.apache.lucene.queryParser.MultiFieldQueryParser;   
  15. import org.apache.lucene.search.IndexSearcher;   
  16. import org.apache.lucene.search.MultiSearcher;   
  17. import org.apache.lucene.search.Query;   
  18. import org.apache.lucene.search.ScoreDoc;   
  19. import org.apache.lucene.search.TopDocCollector;   
  20. import org.apache.lucene.search.highlight.Highlighter;   
  21. import org.apache.lucene.search.highlight.QueryScorer;   
  22. import org.apache.lucene.search.highlight.SimpleFragmenter;   
  23. import org.apache.lucene.search.highlight.SimpleHTMLFormatter;   
  24.   
  25. public class SerchIndex {   
  26.   
  27.     /**  
  28.      * 执行查询方法  
  29.      *   
  30.      * @param <T> 需要转换的Bean类型  
  31.      * @param cls Bean类的class对象  
  32.      * @param keyword 关键字  
  33.      * @param indexPath 索引所在的目录  
  34.      * @param rowCount 每页显示的记录数  
  35.      * @param current 当前需要查看的页数  
  36.      * @return  
  37.      * @throws Exception  
  38.      */  
  39.     public <T> List<T> initSearch(Class<T> cls, String keyword, int rowCount,int current, String... indexPaths)throws Exception{   
  40.   
  41.         /* 用来保存填充完毕的返回对象 */  
  42.         List<T> objs = new ArrayList<T>();   
  43.         /* 分词器 StandardAnalyzer 按字分词,支持中文分词 */  
  44.         Analyzer analyzer = new StandardAnalyzer();   
  45.         Field[] fields = cls.getDeclaredFields();   
  46.         /* 关键字都去匹配那些列 */  
  47.         String[] colmuns = new String[fields.length];   
  48.         /* 查询关键字 */  
  49.         String[] keyWords = new String[fields.length];   
  50.         for(int i =0;i < fields.length; i++){   
  51.             colmuns[i] = fields[i].getName();   
  52.             keyWords[i] = keyword;   
  53.         }   
  54.         if(indexPaths == null || indexPaths.length <= 0){   
  55.             return objs;   
  56.         }   
  57.         IndexSearcher[] searchers = new IndexSearcher[indexPaths.length];   
  58.         for(int i = 0; i < indexPaths.length; i++){   
  59.             /* 索引读取对象 */  
  60.             IndexReader reader = IndexReader.open(indexPaths[i]);   
  61.             /* 创建索引查询对象 */  
  62.             searchers[i] = new IndexSearcher(reader);   
  63.         }   
  64.         MultiSearcher multisearcher = new MultiSearcher(searchers);   
  65.         Query query = MultiFieldQueryParser.parse(keyWords, colmuns, analyzer);   
  66.         /* 缓冲记录数 */  
  67.         TopDocCollector collector = new TopDocCollector(rowCount);   
  68.         /* 执行查询 */  
  69.         multisearcher.search(query,collector);   
  70.         ScoreDoc[] hits = collector.topDocs().scoreDocs;    
  71.   
  72.         for(int i = (current - 1) * rowCount;i<current * rowCount; i++){   
  73.             int docId = hits[i].doc;   
  74.             Document doc = multisearcher.doc(docId);   
  75.             T obj = cls.newInstance();   
  76.             for(int j =0;j < fields.length; j++){   
  77.                 String str = doc.get(fields[j].getName());   
  78.                 /* 搜索关键字高亮处理 */  
  79.                 SimpleHTMLFormatter sHtmlF = new SimpleHTMLFormatter("<font color='red'>""</font>");      
  80.                 Highlighter highlighter = new Highlighter(sHtmlF,new QueryScorer(query));      
  81.                 highlighter.setTextFragmenter(new SimpleFragmenter(100));    
  82.                 if (str != null && !"".equals(str)) {      
  83.                     TokenStream tokenStream = analyzer.tokenStream(fields[j].getName(), new StringReader(str));   
  84.                     String value  = highlighter.getBestFragment(tokenStream, str);   
  85.                     /* 如果不存在关键字依然显示 */  
  86.                     if(value != null && !"".equals(value)){   
  87.                         BeanUtils.setProperty(obj, fields[j].getName(), value);   
  88.                     }else{   
  89.                         BeanUtils.setProperty(obj, fields[j].getName(), str);   
  90.                     }   
  91.                 }   
  92.             }   
  93.             objs.add(obj);   
  94.         }   
  95.         multisearcher.close();   
  96.         return objs;   
  97.     }   
  98. }  

以上3个类就是我主要的扩张类,方法都有注释,大家有不明白的可以留言询问。
测试类:
SerchTest.java
Java代码 复制代码
  1. package ordinov.luceneServ;   
  2.   
  3. import java.io.IOException;   
  4. import java.lang.reflect.InvocationTargetException;   
  5. import java.sql.SQLException;   
  6. import java.util.List;   
  7.   
  8. import ordinov.dao.Dao;   
  9. import ordinov.model.User;   
  10.   
  11. import org.apache.lucene.index.CorruptIndexException;   
  12. import org.apache.lucene.store.LockObtainFailedException;   
  13.   
  14. import com.ordinov.lucene.SerchIndex;   
  15. import com.ordinov.lucene.IndexManger;   
  16.   
  17. public class SerchTest {   
  18.     public static void main(String [] args){   
  19.   
  20.         try {   
  21. //          String sql="select * from asso_main_material t where ROWNUM <= 5000";   
  22.             String sql="select * from asso_main_material t where 5000 <= ROWNUM and ROWNUM <= 10000";   
  23.             System.out.println(sql);   
  24.             Dao dao = new Dao();   
  25.             List<User> users = dao.query(sql);   
  26.             IndexManger index = new IndexManger("D:/benjamin2",null,true);   
  27.             index.createIndex(User.class, users.toArray(new User[0]));   
  28.         } catch (SQLException e) {   
  29.             e.printStackTrace();   
  30.         } catch (CorruptIndexException e) {   
  31.             e.printStackTrace();   
  32.         } catch (LockObtainFailedException e) {   
  33.             e.printStackTrace();   
  34.         } catch (IOException e) {   
  35.             e.printStackTrace();   
  36.         } catch (IllegalAccessException e) {   
  37.             e.printStackTrace();   
  38.         } catch (InvocationTargetException e) {   
  39.             e.printStackTrace();   
  40.         } catch (NoSuchMethodException e) {   
  41.             e.printStackTrace();   
  42.         }   
  43.            
  44.         try {   
  45.             SerchIndex si = new SerchIndex();   
  46.             List<User> users = si.initSearch(User.class"院"301,"D:/benjamin1","D:/benjamin2");   
  47.             for(User user : users){   
  48.                 System.out.println(user.getId());   
  49.                 System.out.println(user.getHome_Adress());   
  50.                 System.out.println(user.getHomeTown());   
  51.                 System.out.println(user.getUnit_Dept());   
  52.                 System.out.println(user.getUnit_Duty());   
  53.             }   
  54.         } catch (Exception e) {   
  55.             e.printStackTrace();   
  56.         }   
  57.   
  58.     }   
  59. }  

OK 东西就是这些,希望对大家有所帮助!

文章来源:http://www.xinxilong.com

作者:不详 来源:网络
相关评论
发表我的评论
  • 大名:
  • 内容:
  • 石青论坛群发大师(www.xinxilong.com) © 2008 版权所有 All Rights Resverved.
  • Email:433168[at]qq.com 沪ICP备12025887号
  • Powered by 论坛群发大师