lucene 总结

lucene总结

公司项目:portal中期刊文章内容作为大字段存储在Oracle中,首页有一个搜索功能:要求将所有包括搜索字段的文章的标题列出来(文章的内容存储在Oracle的CLOB字段中),也就是要用Lucene实现对数据库的大字段进行索引(索引通过计划任务定时建立索引)和搜索。。。

==================定时建立索引文件:===============

Main方法:

Java代码 复制代码
  1.  package zxt.lucene.index;   
  2.   
  3. import java.util.Timer;   
  4. public class IndexerServer {   
  5.   
  6.        
  7.     /**  
  8.      * 定时调用建立索引任务  
  9.      * @author wulihai  
  10.      * @create 2009-06-02  
  11.      */  
  12.     public static void main(String[] args) {   
  13.         String propFile = "directory.properties";   
  14.         Config.setConfigFileName(propFile);   
  15.         Timer   timer = new Timer();   
  16.         LuceneDBIndexerTask luceneTask=LuceneDBIndexerTask.getInstance();    
  17.         timer.scheduleAtFixedRate(luceneTask, 0,DataTypeUtil.toLong(Constant.CREATE_INDEX_SLEEP_TIME));   
  18.     }   
  19.   
  20. }  



定时调用建立索引任务:

Java代码 复制代码
  1. package zxt.lucene.index;   
  2.   
  3. import java.util.Timer;   
  4. public class IndexerServer {   
  5.   
  6.        
  7.     /**  
  8.      * 定时调用建立索引任务  
  9.      * @author wulihai  
  10.      * @create 2009-06-02  
  11.      */  
  12.     public static void main(String[] args) {   
  13.         String propFile = "directory.properties";   
  14.         Config.setConfigFileName(propFile);   
  15.         Timer   timer = new Timer();   
  16.         LuceneDBIndexerTask luceneTask=LuceneDBIndexerTask.getInstance();    
  17.         timer.scheduleAtFixedRate(luceneTask, 0,DataTypeUtil.toLong(Constant.CREATE_INDEX_SLEEP_TIME));   
  18.     }   
  19.   
  20. }  




建立索引的核心实现:

Java代码 复制代码
  1. package zxt.lucene.index;   
  2. import java.io.BufferedReader;   
  3. import java.io.File;   
  4. import java.io.IOException;   
  5. import java.io.StringWriter;   
  6. import java.sql.Connection;   
  7. import java.sql.DriverManager;   
  8. import java.sql.ResultSet;   
  9. import java.sql.SQLException;   
  10. import java.sql.Statement;   
  11. import java.text.SimpleDateFormat;   
  12. import java.util.Arrays;   
  13. import java.util.Date;   
  14. import java.util.TimerTask;   
  15.   
  16. import oracle.sql.CLOB;   
  17.   
  18. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  19. import org.apache.lucene.document.Document;   
  20. import org.apache.lucene.document.Field;   
  21. import org.apache.lucene.index.IndexWriter;   
  22.   
  23.   /**  
  24.   * 建立索引的任务类  
  25.   * @author wulihai  
  26.   * @create 2009-06-02  
  27.  */  
  28. public class LuceneDBIndexerTask extends TimerTask {   
  29.     //缺省索引目录   
  30.     private static String DEFAULT_INDEX_DIR="C:\\IndexDB";   
  31.      //临时索引目录的父目录   
  32.     private File parentDir=null;   
  33.      //被搜索的索引文件   
  34.     private static LuceneDBIndexerTask index=new LuceneDBIndexerTask();   
  35.        
  36.     //构造方法   
  37.     private LuceneDBIndexerTask(){   
  38.         String dirStr=Constant.INDEX_STORE_DIRECTORY;   
  39.         if(dirStr!=null&&!"".equals(dirStr)){   
  40.             this.parentDir=new File(dirStr);   
  41.            
  42.         }else{   
  43.             this.parentDir=new File(DEFAULT_INDEX_DIR);   
  44.         }   
  45.            
  46.         if(!this.parentDir.exists()){   
  47.             this.parentDir.mkdir();   
  48.         }   
  49.     }   
  50.        
  51.     /**  
  52.      * 单实例访问接口  
  53.      * @return  
  54.      */  
  55.     public static LuceneDBIndexerTask getInstance(){   
  56.         return index;   
  57.     }   
  58.        
  59.      /**  
  60.      * 锁定目录以及文件  
  61.      * 只允许单线程访问  
  62.      *  
  63.      */  
  64.     /*public synchronized  void singleRunning(){  
  65.         if(flag==false){  
  66.             flag=true;  
  67.             run(parentDir);   
  68.         }  
  69.     }*/  
  70.   
  71.      /**  
  72.      * 为数据库字段建立索引  
  73.      */  
  74.     public  void run()  {   
  75.         System.out.println("====LuceneDBIndexerTask$run()===============");   
  76.            
  77.         System.out.println("~~~开始建立索引文件~~~~~~~~~~~~~~~");   
  78.         Connection conn=null;   
  79.         Statement stmt=null;   
  80.         ResultSet rs=null;   
  81.         try {   
  82.             Class.forName(Constant.DB_DRIVER_STRING);   
  83.              conn = DriverManager.getConnection(Constant.DB_URI_STRING, Constant.DB_USERNAME, Constant.DB_PWD);   
  84.              stmt = conn.createStatement();   
  85.              rs = stmt.executeQuery(Constant.DB_QUERY_STRING);   
  86.              File file=new File(parentDir+File.separator+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+File.separator);   
  87.              if(!file.exists()){   
  88.                  file.mkdir();   
  89.              }   
  90.             IndexWriter writer = new IndexWriter(file,new StandardAnalyzer(), true);   
  91.             long startTime = new Date().getTime();   
  92.             while (rs.next()) {   
  93.                 Document doc = new Document();   
  94.                  doc.add(new Field("ARTICLEID", rs.getString("ARTICLEID"), Field.Store.YES,Field.Index.TOKENIZED));   
  95.                  doc.add(new Field("TITLE", rs.getString("TITLE"), Field.Store.YES,Field.Index.TOKENIZED));   
  96.                  doc.add(new Field("USERNAME", rs.getString("USERNAME"), Field.Store.YES,Field.Index.TOKENIZED));   
  97.                  doc.add(new Field("USERID", rs.getString("USERID"), Field.Store.YES,Field.Index.TOKENIZED));   
  98.                  //对日期建立索引   
  99.                  String createdate=new SimpleDateFormat("yyyy-MM-dd").format(rs.getTimestamp("CREATEDATE"));   
  100.                  doc.add(new Field("CREATEDATE", createdate, Field.Store.YES,Field.Index.TOKENIZED));   
  101.                  //对大字段建立索引   
  102.                  BufferedReader in=null;   
  103.                  String content="";   
  104.                  CLOB clob =  (CLOB) rs.getClob("CONTENT");   
  105.                  if (clob != null) {   
  106.                     //得到一个读入流   
  107.                   in=new BufferedReader(clob.getCharacterStream());   
  108.                   StringWriter out=new StringWriter();   
  109.                   int c;   
  110.                   while((c=in.read())!=-1){   
  111.                       out.write(c);   
  112.                    }   
  113.                   content=out.toString();   
  114.                 }   
  115.                 doc.add(new Field("CONTENT", content, Field.Store.YES, Field.Index.TOKENIZED));   
  116.                 writer.addDocument(doc);   
  117.             }   
  118.             writer.optimize();   
  119.             writer.close();   
  120.                
  121.             //测试一下索引的时间      
  122.             long endTime = new Date().getTime();   
  123.             System.out.println("索引文件"+file.getPath()+"建立成功...");   
  124.             System.out.println("这花费了" + (endTime - startTime) + " 毫秒来把文档增加到索引里面去!");   
  125.                
  126.                    
  127.             //判断文件目录file下的文件个数如果大于3,就将文件建立最早的文件给删除掉   
  128.             checkFiles(parentDir);   
  129.                
  130.         } catch (IOException e) {   
  131.             e.printStackTrace();   
  132.         } catch (SQLException e) {   
  133.             e.printStackTrace();   
  134.         } catch (ClassNotFoundException e) {   
  135.             e.printStackTrace();   
  136.                
  137.         }finally{   
  138.          try {   
  139.              if(rs!=null){   
  140.                rs.close();      
  141.              }   
  142.              if(stmt!=null){   
  143.                  stmt.close();      
  144.               }    
  145.              if(conn!=null){   
  146.                  conn.close();      
  147.               }    
  148.             } catch (SQLException e) {   
  149.                 e.printStackTrace();   
  150.             }   
  151.         }   
  152.     }   
  153.        
  154.      /**  
  155.      * 判断文件目录file下的文件个数如果大于3,就将文件建立最早的文件给删除掉  
  156.      */  
  157.     public  void checkFiles(File dir) {   
  158.         int length=dir.listFiles().length;   
  159.         while(length>3){   
  160.             //删除生成最早的文件   
  161.          File [] files=dir.listFiles();   
  162.          String[] names=dir.list();   
  163.          Arrays.sort(names);   
  164.          File deletefile=files[0];   
  165.          deleteDirectory(deletefile);   
  166.          length--;   
  167.        }   
  168.            
  169.     }   
  170.        
  171.     /*  
  172.      * 递归删除一个目录以及下面的文件  
  173.      */  
  174.     public boolean deleteDirectory(File path) {      
  175.         if( path.exists() ) {      
  176.           File[] files = path.listFiles();      
  177.           for(int i=0; i<files.length; i++) {      
  178.              if(files.isDirectory()) {      
  179.                deleteDirectory(files);     
  180.                  
  181.              }      
  182.              else {      
  183.                  //删除文件   
  184.                files.delete();      
  185.              }      
  186.           }      
  187.         }      
  188.         //删除目录   
  189.         boolean hasdelete=path.delete();   
  190.         if(hasdelete){   
  191.             System.out.println("删除索引目录"+path);   
  192.                
  193.         }   
  194.         return hasdelete;   
  195.            
  196.            
  197.       }      
  198.          
  199.   
  200.        
  201.        
  202.        
  203.     public static void main(String[] args) {   
  204.       new LuceneDBIndexerTask().run();   
  205.            
  206.     }   
  207.   
  208.   
  209.   
  210. }  




配置文件管理类:

Java代码 复制代码
  1. package zxt.lucene.index;   
  2.   
  3. import java.io.IOException;   
  4. import java.io.InputStream;   
  5. import java.util.Properties;   
  6.   
  7. /**  
  8.  *   
  9.  * @author wulihai  
  10.  * @create 2009-06-02  
  11.  *  
  12.  */  
  13. public class Config {   
  14.   
  15.     private static Config cfg = null;   
  16.   
  17.     private static String configFileName = null;   
  18.   
  19.     private Properties props;   
  20.   
  21.     public Config() {   
  22.         props = new java.util.Properties();   
  23.     }   
  24.   
  25.     /**  
  26.      * 单例访问接口  
  27.      * @return  
  28.      */  
  29.     public synchronized static Config getInstance() {   
  30.         if (cfg == null) {   
  31.             cfg = new Config();   
  32.             cfg.loadConfig();   
  33.             return cfg;   
  34.         } else {   
  35.             return cfg;   
  36.         }   
  37.   
  38.     }   
  39.   
  40.     private int loadConfig() {   
  41.         if (configFileName != null || configFileName.length() > 0) {   
  42.             InputStream inputStream = Config.class.getClassLoader()   
  43.                     .getResourceAsStream("directory.properties");   
  44.             System.out.println("configFileName=" + configFileName);   
  45.             try {   
  46.                 props.load(inputStream);   
  47.             } catch (IOException e) {   
  48.                 e.printStackTrace();   
  49.             }   
  50.             return 1;   
  51.         }   
  52.         return 0;   
  53.   
  54.     }   
  55.   
  56.     public static void setConfigFileName(String cfg) {   
  57.         configFileName = cfg;   
  58.     }   
  59.   
  60.     public String getProperty(String keyName) {   
  61.         return props.getProperty(keyName);   
  62.     }   
  63.   
  64. }  



常量配置

Java代码 复制代码
  1. package zxt.lucene.index;   
  2.   
  3. /**  
  4.  * 常量配置类 *  
  5.  * @author wulihai  
  6.  * @create 2009-06-02  
  7.  */  
  8. public class Constant {   
  9.   
  10.     // 隔多长时间建立一次索引   
  11.     public static final String CREATE_INDEX_SLEEP_TIME = Config.getInstance()   
  12.             .getProperty("create_index_sleep_time");   
  13.   
  14.     // 索引文件存放路径   
  15.     public static final String INDEX_STORE_DIRECTORY = Config.getInstance()   
  16.             .getProperty("index_store_directory");   
  17.     //数据库驱动程序   
  18.     public static final String DB_DRIVER_STRING = Config.getInstance()   
  19.     .getProperty("db_driver_string");   
  20.     //数据库连接URI   
  21.     public static final String DB_URI_STRING = Config.getInstance()   
  22.     .getProperty("db_uri_string");   
  23.     //数据库连接username   
  24.     public static final String DB_USERNAME= Config.getInstance()   
  25.     .getProperty("db_username");   
  26.      //数据库连接pwd   
  27.     public static final String DB_PWD= Config.getInstance()   
  28.     .getProperty("db_pwd");   
  29.     //数据库查询语句db_query_str   
  30.     public static final String DB_QUERY_STRING= Config.getInstance()   
  31.     .getProperty("db_query_string");   
  32.        
  33. }  



数据类型处理类:

Java代码 复制代码
  1. package zxt.lucene.index;   
  2.   
  3. /**  
  4.  * 数据类型转换工具类  
  5.  * @author wulihai  
  6.  * @create 2009-06-02  
  7.  */  
  8. public class DataTypeUtil {   
  9.      /**  
  10.      * 将对象转换为整数型  
  11.      * @param o  源对象  
  12.      * @return 对应的Long值,如果出错,则返回Long.MIN_VALUE  
  13.      */  
  14.     public static long toLong(Object o) {   
  15.         if (o == null) {   
  16.             throw new IllegalArgumentException("该对象为空");   
  17.         }   
  18.         String s = o.toString();   
  19.         try {   
  20.             return Long.parseLong(s);   
  21.         } catch (Exception ex) {   
  22.             return Long.MAX_VALUE;   
  23.         }   
  24.     }   
  25. }  




配置文件 :

Properties代码 复制代码
  1.   
  2. #== the directory for store lucene-index ========#   
  3. index_store_directory=D:/lucene/indexDB/   
  4.   
  5. #======== two hours ========#   
  6. #create_index_sleep_time=7200000  
  7.   
  8. #======== two minutes ========#   
  9. create_index_sleep_time=120000  
  10.   
  11. db_driver_string=oracle.jdbc.driver.OracleDriver   
  12. db_uri_string=jdbc:oracle:thin:@localhost:1521:lportal   
  13. db_username=lportal   
  14. db_pwd=lportal   
  15. db_query_string=SELECT  * from journalarticle  



==================搜索类:===============

核心搜索类:

Java代码 复制代码
  1. package com.liferay.portal.util;   
  2.   
  3. import java.io.File;   
  4. import java.io.IOException;   
  5. import java.io.InputStream;   
  6. import java.text.SimpleDateFormat;   
  7. import java.util.ArrayList;   
  8. import java.util.Arrays;   
  9. import java.util.Date;   
  10. import java.util.List;   
  11.   
  12. import org.apache.lucene.analysis.Analyzer;   
  13. import org.apache.lucene.analysis.standard.StandardAnalyzer;   
  14. import org.apache.lucene.document.Document;   
  15. import org.apache.lucene.queryParser.ParseException;   
  16. import org.apache.lucene.queryParser.QueryParser;   
  17. import org.apache.lucene.search.Hits;   
  18. import org.apache.lucene.search.IndexSearcher;   
  19. import org.apache.lucene.search.Query;   
  20. import org.apache.lucene.store.Directory;   
  21. import org.apache.lucene.store.FSDirectory;   
  22. import com.liferay.portlet.journal.model.JournalArticle;   
  23.   
  24. /**  
  25.  * 负责搜索的类  
  26.  */  
  27. public class LuceneDBQuery {   
  28.   
  29.     private static LuceneDBQuery search = new LuceneDBQuery();   
  30.   
  31.     // 构造方法   
  32.     private LuceneDBQuery() {   
  33.   
  34.     }   
  35.   
  36.     /**  
  37.      * 单实例访问接口  
  38.      *   
  39.      * @return  
  40.      */  
  41.     public static LuceneDBQuery getInstance() {   
  42.         return search;   
  43.     }   
  44.   
  45.     /**  
  46.      * 搜索方法  
  47.      *   
  48.      * @throws java.text.ParseException  
  49.      * @throws Exception  
  50.      */  
  51.     public List search(String queryString) {   
  52.         int count = 0;   
  53.         long startTime = new Date().getTime();   
  54.         Hits hits = null;   
  55.   
  56.         // 搜索目录   
  57.         File searchDir = null;   
  58.         Query query = null;   
  59.         InputStream inputStream=null;;   
  60.          String filePath="index.xml";   
  61.          String indexDir="";   
  62.          indexDir= LuceneDBQueryUtil.getIndexPath();   
  63.              
  64.         if (indexDir != null && !"".equals(indexDir)) {   
  65.             searchDir = new File(indexDir);   
  66.             if(!searchDir.exists()){   
  67.                 searchDir.mkdir();   
  68.             }   
  69.         }   
  70.         // 这里注意索引存放的目录的父目录   
  71.         // searchDir=new File("E:\\index\\indexDB\\");   
  72.         File targetDir = getTargetDir(searchDir);   
  73.         IndexSearcher searcher = null;   
  74.         List results = new ArrayList();   
  75.   
  76.         try {   
  77.             Directory dir=FSDirectory.getDirectory(targetDir,false);   
  78.             searcher = new IndexSearcher(dir);   
  79.         } catch (Exception e1) {   
  80.             e1.printStackTrace();   
  81.             System.out.println("创建索引对象出现异常...");   
  82.         }    
  83.         Analyzer analyzer = new StandardAnalyzer();   
  84.   
  85.         // 构建查询对象Query,对CONTENT字段进行搜索   
  86.         QueryParser qp = new QueryParser("CONTENT", analyzer);   
  87.         try {   
  88.             query = qp.parse(queryString);   
  89.         } catch (ParseException e1) {   
  90.             e1.printStackTrace();   
  91.         }   
  92.   
  93.         if (searcher != null) {   
  94.   
  95.             // 得到搜索结果Hits   
  96.             try {   
  97.                 hits = searcher.search(query);   
  98.             } catch (IOException e1) {   
  99.                 System.out.println("查询索引库出现异常...");   
  100.                 e1.printStackTrace();   
  101.             }   
  102.             // 查到的记录条数   
  103.             count = hits.length();   
  104.             if (hits.length() > 0) {   
  105.                 for (int i = 0; i < hits.length(); i++) {// 输出搜索信息   
  106.                     JournalArticle article = new JournalArticle();   
  107.                     Document document = null;   
  108.                     try {   
  109.                         document = hits.doc(i);   
  110.                     } catch (Exception e1) {   
  111.                         System.out.println("返回查询结果集出现异常...");   
  112.                         e1.printStackTrace();   
  113.                     }    
  114.                     try {   
  115.                         article.setDisplayDate(new SimpleDateFormat("yyyyMMdd")   
  116.                                 .parse(document.get("CREATEDATE")));   
  117.                         article.setCreateDate(new SimpleDateFormat("yyyyMMdd")   
  118.                                 .parse(document.get("CREATEDATE")));   
  119.                     } catch (java.text.ParseException e) {   
  120.                         e.printStackTrace();   
  121.                     }   
  122.                     article.setTitle(document.get("TITLE"));   
  123.                     article.setArticleId(document.get("ARTICLEID"));   
  124.                     article.setUserName(document.get("USERNAME"));   
  125.                     article.setUserId(document.get("USERID"));   
  126.                     results.add(article);   
  127.                 }   
  128.                 // 测试一下索引的时间   
  129.                 long endTime = new Date().getTime();   
  130.                 System.out.println("查询过程花费了" + (endTime - startTime) + " 毫秒!");   
  131.             } else {   
  132.                 System.out.println("0个结果!");   
  133.             }   
  134.         }   
  135.   
  136.         return results;   
  137.   
  138.     }   
  139.   
  140.     /**  
  141.      * 确定搜索索引所在目录目录  
  142.      */  
  143.     private File getTargetDir(File dir) {   
  144.         int length = dir.listFiles().length;   
  145.         File searchFile = null;   
  146.   
  147.         // length=3的时候最多   
  148.         // 同时搜索和同时建索引的时候会出现length=4   
  149.         if (length >= 2) {   
  150.             // 找到次最新建立的索引文件   
  151.             String[] names = dir.list();   
  152.             Arrays.sort(names);   
  153.             searchFile = new File(dir + File.separator + names[length - 2]);   
  154.         }   
  155.         if (length == 1) {   
  156.             File files[] = dir.listFiles();   
  157.             searchFile = files[0];   
  158.         }   
  159.         if (length == 0) {   
  160.             // 如果没有索引文件则,建立第一个索引   
  161.             // TestDBIndexer.getInstance().isInstanceRunning();   
  162.             // search();   
  163.         }   
  164.   
  165.         return searchFile;   
  166.     }   
  167. //   
  168. //  public static void main(String[] args) throws Exception {   
  169. //      new LuceneDBQuery().search("纳税人");   
  170. //  }   
  171.   
  172. }  



配置文件管理类:

Java代码 复制代码
  1.   
  2. package com.liferay.portal.util;   
  3.   
  4. import java.io.IOException;   
  5.   
  6. import org.jdom.Document;   
  7. import org.jdom.Element;   
  8. import org.jdom.JDOMException;   
  9. import org.jdom.input.SAXBuilder;   
  10.   
  11. public class LuceneDBQueryUtil {   
  12.        
  13.  public static String getIndexPath(){   
  14.   
  15.         String filePath = "zxt_index.xml";   
  16.         String indexPath="";   
  17.         SAXBuilder builder = new SAXBuilder(false);   
  18.         try {   
  19.             Document doc = builder.build(Thread.currentThread().getContextClassLoader().getResource(filePath));   
  20.             Element rootElement = doc.getRootElement();   
  21.              Element index=rootElement.getChild("index");   
  22.              indexPath=index.getText();   
  23.              System.out.println(indexPath);   
  24.         } catch (JDOMException e) {   
  25.             e.printStackTrace();   
  26.         } catch (IOException e) {   
  27.             e.printStackTrace();   
  28.         }   
  29.         return indexPath;   
  30.   
  31.        
  32.  }   
  33. }  

 

配置文件:zxt_index.xml

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <list>  
  3.  <index>D:\\index\\IndexDB</index>  
  4. </list>  
原文地址:https://www.cnblogs.com/zhonghan/p/1633634.html