• 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>  
  • 相关阅读:
    react学习总结(一)
    jQuery的attr()与prop()的区别
    Vue.js学习(常用指令)
    Node.js学习(篇章一)
    CSS3关于-webkit-tap-highlight-color属性
    position布局影响点击事件以及冒泡获取事件目标
    取消事件默认行为(移动端)
    rem与px之间的换算(移动端)
    Node.js(初识)
    ES6(变量的解构赋值)
  • 原文地址:https://www.cnblogs.com/zhonghan/p/1633634.html
Copyright © 2020-2023  润新知