Lucene检索数据库

来源:互联网 发布:淘宝代做毕业设计被骗 编辑:程序博客网 时间:2024/04/29 03:37

原贴地址:http://www.javaeye.com/topic/963438

全文分两部分:

一:Lucene简介

      Lucene版本:3.0.2

     全文检索大体分两个部分:索引创建(Indexing)和搜索索引(Search

     1. 索引过程:

        1) 有一系列被索引文件(此处所指即数据库数据)

        2) 被索引文件经过语法分析和语言处理形成一系列词(Term)

        3) 经过索引创建形成词典和反向索引表。

        4) 通过索引存储将索引写入硬盘。

    2. 搜索过程:

       a) 用户输入查询语句。

       b) 对查询语句经过语法分析和语言分析得到一系列词(Term)

       c) 通过语法分析得到一个查询树。

       d) 通过索引存储将索引读入到内存。

       e) 利用查询树搜索索引,从而得到每个词(Term)的文档链表,对文档链表进行交,差,并得到结果文档。

       f) 将搜索到的结果文档对查询的相关性进行排序。

       g) 返回查询结果给用户。

 

 

   • 索引过程如下:

       ◦ 创建一个IndexWriter用来写索引文件,它有几个参数,INDEX_DIR就是索引文件所存放的位置,Analyzer便是用来对文档进行词法分析和语言处理的。

       ◦ 创建一个Document代表我们要索引的文档。

       ◦ 将不同的Field加入到文档中。我们知道,一篇文档有多种信息,如题目,作者,修改时间,内容等。不同类型的信息用不同的Field来表示,在本例子中,一共有两类信息进行了索引,一个是文件路径,一个是文件内容。其中FileReaderSRC_FILE就表示要索引的源文件。

       ◦ IndexWriter调用函数addDocument将索引写到索引文件夹中。

   • 搜索过程如下:

       ◦ IndexReader将磁盘上的索引信息读入到内存,INDEX_DIR就是索引文件存放的位置。

       ◦ 创建IndexSearcher准备进行搜索。

       ◦ 创建Analyer用来对查询语句进行词法分析和语言处理。

       ◦ 创建QueryParser用来对查询语句进行语法分析。

       ◦ QueryParser调用parser进行语法分析,形成查询语法树,放到Query中。

       ◦ IndexSearcher调用search对查询语法树Query进行搜索,得到结果TopScoreDocCollector

二:代码示例(本文重点部分)

      1) 首先是连接数据库的jdbc配置文件信息以及存放索引文件的路径配置信息

Test.properties代码  收藏代码
  1. jdbc.driverClassName = com.mysql.jdbc.Driver  
  2. jdbc.url = jdbc:mysql://192.168.0.1/dbname?autoReconnect=true&characterEncoding=utf8  
  3. jdbc.username = root  
  4. jdbc.password = password  
  5. jdbc.maxIdle = 2  
  6. jdbc.maxActive = 4  
  7. jdbc.maxWait = 5000  
  8. jdbc.validationQuery = select 0  
  9. res.index.indexPath = D/://apache-tomcat-6.0.18//webapps//test//testHome//search//res//index1  
  10. res.index.mainDirectory = D/://apache-tomcat-6.0.18//webapps//test//testHome//search//res  

     2) 读取资源文件的工具类:

Java代码  收藏代码
  1. package com.test.common;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.util.HashMap;  
  6. import java.util.Map;  
  7. import java.util.Properties;  
  8.   
  9. /**   
  10.  * PropertiesUtil.java 
  11.  * @version 1.0 
  12.  * @createTime 读取配置文件信息类 
  13.  */  
  14. public class PropertiesUtil {  
  15.   
  16.     private static String defaultPropertyFilePath = "/test.properties";  
  17.       
  18.     private static Map<String,Properties> ppsMap = new HashMap<String,Properties>();  
  19.       
  20.     /** 
  21.      * 读取默认文件的配置信息,读key返回value 
  22.      * @param key 
  23.      * @return value 
  24.      */  
  25.     public static final String getPropertyValue(String key) {  
  26.         Properties pps = getPropertyFile(defaultPropertyFilePath);  
  27.         return pps == null ? null : pps.getProperty(key);  
  28.     }  
  29.       
  30.     /** 
  31.      * 传入filePath读取指定property文件,读key返回value 
  32.      * @param propertyFilePath 
  33.      * @param key 
  34.      * @return value 
  35.      */  
  36.     public static String getPropertyValue(String propertyFilePath,String key) {  
  37.         if(propertyFilePath == null) {  
  38.             propertyFilePath = defaultPropertyFilePath;  
  39.         }  
  40.         Properties pps = getPropertyFile(propertyFilePath);  
  41.         return pps == null ? null : pps.getProperty(key);  
  42.     }  
  43.       
  44.     /** 
  45.      * 根据path返回property文件,并保存到HashMap中,提高效率 
  46.      * @param propertyFilePath 
  47.      * @return 
  48.      */  
  49.     public static Properties getPropertyFile(String propertyFilePath) {  
  50.         if(propertyFilePath == null) {  
  51.             return null;  
  52.         }  
  53.         Properties pps = ppsMap.get(propertyFilePath);  
  54.         if(pps == null) {  
  55.             InputStream in = PropertiesUtil.class.getResourceAsStream(propertyFilePath);  
  56.             pps = new Properties();  
  57.             try {  
  58.                 pps.load(in);  
  59.             } catch (IOException e) {  
  60.                 e.printStackTrace();  
  61.             }  
  62.             ppsMap.put(propertyFilePath, pps);  
  63.         }  
  64.           
  65.         return pps;  
  66.     }  
  67. }  

      3) Jdbc连接数据库获取Connection工具类,不做分析,直接上代码

Java代码  收藏代码
  1. package com.test.common;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.DriverManager;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7. import java.sql.Statement;  
  8.   
  9. /**   
  10.  * JdbcUtil.java 
  11.  * @version 1.0 
  12.  * @createTime JDBC获取Connection工具类 
  13.  */  
  14. public class JdbcUtil {  
  15.       
  16.     private static Connection conn = null;  
  17.       
  18.     private static final String URL;  
  19.       
  20.     private static final String JDBC_DRIVER;  
  21.       
  22.     private static final String USER_NAME;  
  23.       
  24.     private static final String PASSWORD;  
  25.       
  26.     static {  
  27.         URL = PropertiesUtil.getPropertyValue("jdbc.url");  
  28.         JDBC_DRIVER = PropertiesUtil.getPropertyValue("jdbc.driverClassName");  
  29.         USER_NAME = PropertiesUtil.getPropertyValue("jdbc.username");  
  30.         PASSWORD = PropertiesUtil.getPropertyValue("jdbc.password");  
  31.     }  
  32.       
  33.     public static Connection getConnection() {  
  34.         try {  
  35.             Class.forName(JDBC_DRIVER);  
  36.             conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);  
  37.         } catch (ClassNotFoundException e) {  
  38.             e.printStackTrace();  
  39.         } catch (SQLException e) {  
  40.             e.printStackTrace();  
  41.         }  
  42.         return conn;  
  43.     }  
  44.       
  45. }  

     4) 万事具备,只欠东风了,下面是核心部分,方法都有注释,不多说了,一步步来,我想肯定是没有问题的。代码如下:

Java代码  收藏代码
  1. package com.test.lucene.logic;  
  2.   
  3. import java.io.File;  
  4. import java.sql.Connection;  
  5. import java.sql.ResultSet;  
  6. import java.sql.Statement;  
  7. import java.util.ArrayList;  
  8. import java.util.List;  
  9.   
  10. import org.apache.lucene.analysis.Analyzer;  
  11. import org.apache.lucene.document.Document;  
  12. import org.apache.lucene.document.Field;  
  13. import org.apache.lucene.document.Field.TermVector;  
  14. import org.apache.lucene.index.IndexWriter;  
  15. import org.apache.lucene.queryParser.QueryParser;  
  16. import org.apache.lucene.search.IndexSearcher;  
  17. import org.apache.lucene.search.Query;  
  18. import org.apache.lucene.search.ScoreDoc;  
  19. import org.apache.lucene.search.Searcher;  
  20. import org.apache.lucene.search.TopDocs;  
  21. import org.apache.lucene.store.Directory;  
  22. import org.apache.lucene.store.FSDirectory;  
  23. import org.apache.lucene.util.Version;  
  24. import org.wltea.analyzer.lucene.IKAnalyzer;  
  25. import org.wltea.analyzer.lucene.IKSimilarity;  
  26.   
  27. import com.test.common.JdbcUtil;  
  28. import com.test.common.PropertiesUtil;  
  29. import com.test.lucene.model.SearchBean;  
  30.   
  31. /**   
  32.  * SearchLogic.java 
  33.  * @version 1.0 
  34.  * @createTime Lucene数据库检索 
  35.  */  
  36. public class SearchLogic {  
  37.   
  38.     private static Connection conn = null;  
  39.       
  40.     private static Statement stmt = null;  
  41.       
  42.     private static  ResultSet rs = null;  
  43.       
  44.     private String searchDir = PropertiesUtil.getPropertyValue("res.index.indexPath");  
  45.       
  46.     private static File indexFile = null;  
  47.       
  48.     private static Searcher searcher = null;  
  49.       
  50.     private static Analyzer analyzer = null;  
  51.       
  52.     /** 索引页面缓冲 */  
  53.     private int maxBufferedDocs = 500;  
  54.     /** 
  55.      * 获取数据库数据 
  56.      * @return ResultSet 
  57.      * @throws Exception 
  58.      */  
  59.     public List<SearchBean> getResult(String queryStr) throws Exception {  
  60.           
  61.         List<SearchBean> result = null;  
  62.         conn = JdbcUtil.getConnection();  
  63.         if(conn == null) {  
  64.             throw new Exception("数据库连接失败!");  
  65.         }  
  66.         String sql = "select articleid,title_en,title_cn,abstract_en,abstract_cn from p2p_jour_article";  
  67.         try {  
  68.             stmt = conn.createStatement();  
  69.             rs = stmt.executeQuery(sql);  
  70.             this.createIndex(rs);   //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引  
  71.             TopDocs topDocs = this.search(queryStr);  
  72.   
  73.             ScoreDoc[] scoreDocs = topDocs.scoreDocs;  
  74.               
  75.             result = this.addHits2List(scoreDocs);  
  76.         } catch(Exception e) {  
  77.             e.printStackTrace();  
  78.             throw new Exception("数据库查询sql出错! sql : " + sql);  
  79.         } finally {  
  80.             if(rs != null) rs.close();  
  81.             if(stmt != null) stmt.close();  
  82.             if(conn != null) conn.close();  
  83.         }  
  84.           
  85.         return result;  
  86.     }  
  87.       
  88.     /** 
  89.      * 为数据库检索数据创建索引 
  90.      * @param rs 
  91.      * @throws Exception 
  92.      */  
  93.     private void createIndex(ResultSet rs) throws Exception {  
  94.           
  95.         Directory directory = null;  
  96.         IndexWriter indexWriter = null;  
  97.           
  98.         try {  
  99.             indexFile = new File(searchDir);  
  100.             if(!indexFile.exists()) {  
  101.                 indexFile.mkdir();  
  102.             }  
  103.             directory = FSDirectory.open(indexFile);  
  104.             analyzer = new IKAnalyzer();  
  105.               
  106.             indexWriter = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);  
  107.             indexWriter.setMaxBufferedDocs(maxBufferedDocs);  
  108.             Document doc = null;  
  109.             while(rs.next()) {  
  110.                 doc = new Document();  
  111.                 Field articleid = new Field("articleid", String.valueOf(rs  
  112.                         .getInt("articleid")), Field.Store.YES,  
  113.                         Field.Index.NOT_ANALYZED, TermVector.NO);  
  114.                 Field abstract_cn = new Field("abstract_cn", rs  
  115.                         .getString("abstract_cn") == null ? "" : rs  
  116.                         .getString("abstract_cn"), Field.Store.YES,  
  117.                         Field.Index.ANALYZED, TermVector.NO);  
  118.                 doc.add(articleid);  
  119.                 doc.add(abstract_cn);  
  120.                 indexWriter.addDocument(doc);  
  121.             }  
  122.               
  123.             indexWriter.optimize();  
  124.             indexWriter.close();  
  125.         } catch(Exception e) {  
  126.             e.printStackTrace();  
  127.         }   
  128.     }  
  129.       
  130.     /** 
  131.      * 搜索索引 
  132.      * @param queryStr 
  133.      * @return 
  134.      * @throws Exception 
  135.      */  
  136.     private TopDocs search(String queryStr) throws Exception {  
  137.   
  138.         if(searcher == null) {  
  139.             indexFile = new File(searchDir);  
  140.             searcher = new IndexSearcher(FSDirectory.open(indexFile));    
  141.         }  
  142.         searcher.setSimilarity(new IKSimilarity());  
  143.         QueryParser parser = new QueryParser(Version.LUCENE_30,"abstract_cn",new IKAnalyzer());  
  144.         Query query = parser.parse(queryStr);  
  145.   
  146.         TopDocs topDocs = searcher.search(query, searcher.maxDoc());  
  147.           
  148.         return topDocs;  
  149.     }  
  150.       
  151.     /** 
  152.      * 返回结果并添加到List中 
  153.      * @param scoreDocs 
  154.      * @return 
  155.      * @throws Exception 
  156.      */  
  157.     private List<SearchBean> addHits2List(ScoreDoc[] scoreDocs ) throws Exception {  
  158.           
  159.         List<SearchBean> listBean = new ArrayList<SearchBean>();  
  160.         SearchBean bean = null;  
  161.         for(int i=0 ; i<scoreDocs.length; i++) {  
  162.             int docId = scoreDocs[i].doc;  
  163.             Document doc = searcher.doc(docId);  
  164.             bean = new SearchBean();  
  165.             bean.setArticleid(doc.get("articleid"));  
  166.             bean.setAbstract_cn(doc.get("abstract_cn"));  
  167.             listBean.add(bean);  
  168.         }  
  169.         return listBean;  
  170.     }  
  171.       
  172.     public static void main(String[] args) {  
  173.         SearchLogic logic = new SearchLogic();  
  174.         try {  
  175.             Long startTime = System.currentTimeMillis();  
  176.             List<SearchBean> result = logic.getResult("急性   肺   潮气量   临床试验");  
  177.             int i = 0;  
  178.             for(SearchBean bean : result) {  
  179.                 if(i == 10break;  
  180.                 System.out.println("bean.name " + bean.getClass().getName()  
  181.                         + " : bean.articleid " + bean.getArticleid()  
  182.                         + " : bean.abstract_cn " + bean.getAbstract_cn());  
  183.                 i++;  
  184.             }  
  185.             System.out.println("searchBean.result.size : " + result.size());  
  186.               
  187.             Long endTime = System.currentTimeMillis();  
  188.             System.out.println("查询所花费的时间为:" + (endTime-startTime)/1000);  
  189.         } catch (Exception e) {  
  190.             e.printStackTrace();  
  191.             System.out.println(e.getMessage());  
  192.         }  
  193.     }  
  194. }  

     5) 第四步用到了一个SearchBean,其实这就是一个javabean文件,包含两个String类型(articleid和abstract_cn)的set、get方法,自己回去补上吧。

        顺便说下数据库表结构:

            tablename随便取,但要跟上面查询中的表对应

            表字段:articleid  int 类型

                        abstract_cn   varchar类型

      对表字段没有太严格的定义,本来就是用来测试的。

     6) 最后给大家提供所使用到的jar包列表:

         IKAnalyzer3.2.5Stable.jar(一位好心人建议我升级一下jar包,呵呵,最新的jar包名为:IKAnalyzer3.2.8.jar ,谢谢了!)

         lucene-analyzers-3.0.2

         lucene-core-3.0.2

         lucene-highlighter-3.0.2

         lucene-memory-3.0.2

         lucene-queries-3.0.2

         mysql-connector-java-5.0.8-bin

   好了,有兴趣的人可以试试吧,代码都经过我测试过了,虽然有些地方代码结构不是特别完整,但只是入门用而已。先有了一个成功能够运行的例子之后才有更多的心情去接着学下去,~_~

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 刚买的猪肝没洗直接炒了怎么办 四个多月的宝宝吃了脏东西怎么办 狗吃了脏东西拉稀呕吐怎么办 五个月宝宝怕吃药导致奶不喝怎么办 蒸锅锅盖吸住了怎么办锅比锅盖要大 豇豆没熟孕妇吃了中毒怎么办 孩子积食拉不出粑粑憋的直哭怎么办 2岁宝宝总是半夜拉粑粑怎么办 金毛拉很臭的稀粑粑怎么办 点餐系统登录后没有菜单怎么办? 环亚在线微交易亏了钱怎么办 钢管舞报了教练班觉得学不会怎么办 微信上聊天被外国人给骗了该怎么办 微信冒充朋友骗走我钱怎么办 凉皮调料水鸡精味精放多了怎么办 吃了地屈孕酮后月经不干不净怎么办 藕片用热水炒后变色了怎么办? 外汇延期收款忘了报告了怎么办 怀孕不小心吃了马生菜怎么办 高压锅的皮圈很容易坏是怎么办 华为应用市场账号密码忘记了怎么办 业主对我们提出批评意见时怎么办 向环保局投诉被公司发现了怎么办 在政务大厅上班被群众投诉怎么办 政府下发的文件通知不履行该怎么办 给私人老板开车不给工资怎么办 给个体老板开车不给工资怎么办 户口转走在人才市场的档案怎么办 外来媳妇转上海户口没有档案怎么办 公务员考试笔试差9分面试怎么办 想从事人事方面的工作没经验怎么办 教师资格考试后户籍转走认定怎么办 总经理离职了作为高管的我怎么办 企业换总经理想换供应商应该怎么办 换了晶振时间还快怎么办 职场两个人都想要你的情况下怎么办 造价起步工资太低又结婚了怎么办 3d保存时写入文件出错怎么办 无经验想在工地承包点小活怎么办 一级建造师挂靠后中标后怎么办 用360对系统修补漏洞很慢怎么办