lucene索引並搜索mysql數據庫

由於對lucene比較感興趣,本人在網上找了點資料,終於成功地用lucene對mysql數據庫進行索引創建併成功搜索,先總結如下:

    首先介紹一個jdbc工具類,用於得到Connection對象:


  1. import java.sql.Connection;     
  2. import java.sql.DriverManager;       
  3. import java.sql.SQLException;    
  4. /**     
  5. * JdbcUtil.java   
  6. * @version 1.0   
  7. * @createTime JDBC獲取Connection工具類   
  8. */    
  9. public class JdbcUtil {     
  10.     private static Connection conn = null;     
  11.     private static final String URL = "jdbc:mysql://127.0.0.1/project?autoReconnect=true&characterEncoding=utf8";     
  12.     private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";     
  13.     private static final String USER_NAME = "root";     
  14.     private static final String PASSWORD = "";  
  15.       
  16.     public static Connection getConnection() {     
  17.         try {     
  18.             Class.forName(JDBC_DRIVER);     
  19.             conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);     
  20.         } catch (ClassNotFoundException e) {     
  21.             e.printStackTrace();     
  22.         } catch (SQLException e) {     
  23.             e.printStackTrace();     
  24.         }     
  25.         return conn;     
  26.     }  
  27. }    

    然後就是本文的主要內容了,對數據庫信息進行索引與對索引進行搜索:


  1. import java.io.File;     
  2. import java.sql.Connection;     
  3. import java.sql.ResultSet;     
  4. import java.sql.Statement;     
  5. import java.util.ArrayList;     
  6. import java.util.List;     
  7. import org.apache.lucene.analysis.Analyzer;     
  8. import org.apache.lucene.document.Document;     
  9. import org.apache.lucene.document.Field;     
  10. import org.apache.lucene.document.Field.TermVector;     
  11. import org.apache.lucene.index.IndexWriter;     
  12. import org.apache.lucene.queryParser.QueryParser;  
  13. import org.apache.lucene.search.*;  
  14. import org.apache.lucene.store.Directory;     
  15. import org.apache.lucene.store.FSDirectory;  
  16. import org.apache.lucene.util.Version;  
  17. import org.wltea.analyzer.lucene.IKAnalyzer;  
  18. import org.wltea.analyzer.lucene.IKSimilarity;     
  19.     
  20. /**     
  21. * SearchLogic.java   
  22. * @version 1.0   
  23. * @createTime Lucene數據庫檢索   
  24. */    
  25. public class SearchLogic {     
  26.     private static Connection conn = null;     
  27.     private static Statement stmt = null;     
  28.     private static  ResultSet rs = null;     
  29.     private String searchDir = "E:\\Test\\Index";     
  30.     private static File indexFile = null;     
  31.     private static Searcher searcher = null;     
  32.     private static Analyzer analyzer = null;     
  33.     /** 索引頁面緩衝 */    
  34.     private int maxBufferedDocs = 500;     
  35.     /**   
  36.     * 獲取數據庫數據   
  37.     * @return ResultSet   
  38.     * @throws Exception   
  39.     */    
  40.     public List<SearchBean> getResult(String queryStr) throws Exception {     
  41.         List<SearchBean> result = null;     
  42.         conn = JdbcUtil.getConnection();     
  43.         if(conn == null) {     
  44.             throw new Exception("數據庫連接失敗!");     
  45.         }     
  46.         String sql = "select id, username, password, type from account";     
  47.         try {     
  48.             stmt = conn.createStatement();     
  49.             rs = stmt.executeQuery(sql);     
  50.             this.createIndex(rs);   //給數據庫創建索引,此處執行一次,不要每次運行都創建索引,以後數據有更新可以後臺調用更新索引     
  51.             TopDocs topDocs = this.search(queryStr);     
  52.             ScoreDoc[] scoreDocs = topDocs.scoreDocs;     
  53.             result = this.addHits2List(scoreDocs);     
  54.         } catch(Exception e) {     
  55.             e.printStackTrace();     
  56.             throw new Exception("數據庫查詢sql出錯! sql : " + sql);     
  57.         } finally {     
  58.             if(rs != null) rs.close();     
  59.             if(stmt != null) stmt.close();     
  60.             if(conn != null) conn.close();     
  61.         }              
  62.         return result;     
  63.     }     
  64.   
  65. /**   
  66. * 爲數據庫檢索數據創建索引   
  67. * @param rs   
  68. * @throws Exception   
  69. */    
  70.     private void createIndex(ResultSet rs) throws Exception {     
  71.         Directory directory = null;     
  72.         IndexWriter indexWriter = null;     
  73.          
  74.         try {     
  75.             indexFile = new File(searchDir);     
  76.             if(!indexFile.exists()) {     
  77.                 indexFile.mkdir();     
  78.             }     
  79.             directory = FSDirectory.open(indexFile);     
  80.             analyzer = new IKAnalyzer();     
  81.               
  82.             indexWriter = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);     
  83.             indexWriter.setMaxBufferedDocs(maxBufferedDocs);     
  84.             Document doc = null;     
  85.             while(rs.next()) {     
  86.                 doc = new Document();     
  87.                 Field id = new Field("id", String.valueOf(rs.getInt("id")), Field.Store.YES, Field.Index.NOT_ANALYZED, TermVector.NO);     
  88.                 Field username = new Field("username", rs.getString("username") == null ? "" : rs.getString("username"), Field.Store.YES,Field.Index.ANALYZED, TermVector.NO);     
  89.                 doc.add(id);     
  90.                 doc.add(username);     
  91.                 indexWriter.addDocument(doc);     
  92.             }     
  93.                          
  94.             indexWriter.optimize();     
  95.             indexWriter.close();     
  96.         } catch(Exception e) {     
  97.             e.printStackTrace();     
  98.         }      
  99.     }     
  100.    
  101.     /**   
  102.     * 搜索索引   
  103.     * @param queryStr   
  104.     * @return   
  105.     * @throws Exception   
  106.     */    
  107.     private TopDocs search(String queryStr) throws Exception {            
  108.         if(searcher == null) {     
  109.             indexFile = new File(searchDir);     
  110.             searcher = new IndexSearcher(FSDirectory.open(indexFile));       
  111.         }     
  112.         searcher.setSimilarity(new IKSimilarity());     
  113.         QueryParser parser = new QueryParser(Version.LUCENE_30,"username",new IKAnalyzer());     
  114.         Query query = parser.parse(queryStr);  
  115.           
  116.         TopDocs topDocs = searcher.search(query, searcher.maxDoc());     
  117.         return topDocs;     
  118.     }  
  119.       
  120.     /**   
  121.     * 返回結果並添加到List中   
  122.     * @param scoreDocs   
  123.     * @return   
  124.     * @throws Exception   
  125.     */    
  126.     private List<SearchBean> addHits2List(ScoreDoc[] scoreDocs ) throws Exception {     
  127.         List<SearchBean> listBean = new ArrayList<SearchBean>();     
  128.         SearchBean bean = null;     
  129.         for(int i=0 ; i<scoreDocs.length; i++) {     
  130.             int docId = scoreDocs[i].doc;     
  131.             Document doc = searcher.doc(docId);     
  132.             bean = new SearchBean();     
  133.             bean.setId(doc.get("id"));     
  134.             bean.setUsername(doc.get("username"));     
  135.             listBean.add(bean);     
  136.         }     
  137.         return listBean;     
  138.     }  
  139.       
  140.     public static void main(String[] args) {     
  141.         SearchLogic logic = new SearchLogic();     
  142.         try {     
  143.             Long startTime = System.currentTimeMillis();     
  144.             List<SearchBean> result = logic.getResult("商家");     
  145.             int i = 0;     
  146.             for(SearchBean bean : result) {     
  147.                 if(i == 10)   
  148.                     break;     
  149.                 System.out.println("bean.name " + bean.getClass().getName() + " : bean.id " + bean.getId()+ " : bean.username " + bean.getUsername());   
  150.                 i++;     
  151.             }  
  152.               
  153.             System.out.println("searchBean.result.size : " + result.size());     
  154.             Long endTime = System.currentTimeMillis();     
  155.             System.out.println("查詢所花費的時間爲:" + (endTime-startTime)/1000);     
  156.         } catch (Exception e) {   
  157.             e.printStackTrace();     
  158.             System.out.println(e.getMessage());     
  159.         }     
  160.     }     
  161. }    

    對了上面的類還用到了一個javabean類,如下:

  1. public class SearchBean {  
  2.     private String id;  
  3.     private String username;  
  4.     public String getId() {  
  5.         return id;  
  6.     }  
  7.     public void setId(String id) {  
  8.         this.id = id;  
  9.     }  
  10.     public String getUsername() {  
  11.         return username;  
  12.     }  
  13.     public void setUsername(String username) {  
  14.         this.username = username;  
  15.     }  
  16. }  

    這些代碼大部分都是我在網上找到的doc文檔中複製粘貼而來,本着“拿來主義”,我對這些代碼修改不大,經測試,這些代碼能夠正常運行。

    寫了幾篇博客,對lucene的使用方式也越來越清楚,在這裏也很有必要總結一下:

    使用lucene包括兩個步驟,分別是索引和搜索。

    •索引過程如下:
       ◦ 創建一個IndexWriter用來寫索引文件,它有幾個參數,INDEX_DIR就是索引文件所存放的位置,Analyzer便是用來對文檔進行詞法分析和語言處理的。
       ◦ 創建一個Document代表我們要索引的文檔。
       ◦ 將不同的Field加入到文檔中。我們知道,一篇文檔有多種信息,如題目,作者,修改時間,內容等。不同類型的信息用不同的Field來表示。
       ◦ IndexWriter調用函數addDocument將索引寫到索引文件夾中。
    •搜索過程如下:
       ◦ IndexReader將磁盤上的索引信息讀入到內存,INDEX_DIR就是索引文件存放的位置。
       ◦ 創建IndexSearcher準備進行搜索。
       ◦ 創建Analyer用來對查詢語句進行詞法分析和語言處理。
       ◦ 創建QueryParser用來對查詢語句進行語法分析。
       ◦ QueryParser調用parser進行語法分析,形成查詢語法樹,放到Query中。
       ◦ IndexSearcher調用search對查詢語法樹Query進行搜索,得到結果TopScoreDocCollector。

    對了,必須說一下,上面的例子還用到了一個新的jar包IKAnalyzer.jar包,它是一個開源的中文分詞器,如果不使用這個分詞器,那麼將無法解析中文,比如說我的第一篇關於Lucene的博客就無法解析中文字符串!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章