由于对lucene比较感兴趣,本人在网上找了点资料,终于成功地用lucene对mysql数据库进行索引创建并成功搜索,先总结如下:
首先介绍一个jdbc工具类,用于得到Connection对象:
[java] view plaincopy
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.SQLException;
- /**
- * JdbcUtil.java
- * @version 1.0
- * @createTime JDBC获取Connection工具类
- */
- public class JdbcUtil {
- private static Connection conn = null;
- private static final String URL = "jdbc:mysql://127.0.0.1/project?autoReconnect=true&characterEncoding=utf8";
- private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
- private static final String USER_NAME = "root";
- private static final String PASSWORD = "";
- public static Connection getConnection() {
- try {
- Class.forName(JDBC_DRIVER);
- conn = DriverManager.getConnection(URL, USER_NAME, PASSWORD);
- catch (ClassNotFoundException e) {
- e.printStackTrace();
- catch (SQLException e) {
- e.printStackTrace();
- }
- return conn;
- }
- }
然后就是本文的主要内容了,对数据库信息进行索引与对索引进行搜索:
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. null;
42. conn = JdbcUtil.getConnection();
43. if(conn == null) {
44. throw new Exception("数据库连接失败!");
45. }
46. "select id, username, password, type from account";
47. try {
48. stmt = conn.createStatement();
49. rs = stmt.executeQuery(sql);
50. this.createIndex(rs); //给数据库创建索引,此处执行一次,不要每次运行都创建索引,以后数据有更新可以后台调用更新索引
51. this.search(queryStr);
52. ScoreDoc[] scoreDocs = topDocs.scoreDocs;
53. 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. null;
72. null;
73.
74. try {
75. new File(searchDir);
76. if(!indexFile.exists()) {
77. indexFile.mkdir();
78. }
79. directory = FSDirectory.open(indexFile);
80. new IKAnalyzer();
81.
82. new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);
83. indexWriter.setMaxBufferedDocs(maxBufferedDocs);
84. null;
85. while(rs.next()) {
86. new Document();
87. new Field("id", String.valueOf(rs.getInt("id")), Field.Store.YES, Field.Index.NOT_ANALYZED, TermVector.NO);
88. 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. new File(searchDir);
110. new IndexSearcher(FSDirectory.open(indexFile));
111. }
112. new IKSimilarity());
113. 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. new ArrayList<SearchBean>();
128. null;
129. for(int i=0 ; i<scoreDocs.length; i++) {
130. int docId = scoreDocs[i].doc;
131. Document doc = searcher.doc(docId);
132. new SearchBean();
133. "id"));
134. "username"));
135. listBean.add(bean);
136. }
137. return listBean;
138. }
139.
140. public static void main(String[] args) {
141. new SearchLogic();
142. try {
143. Long startTime = System.currentTimeMillis();
144. "商家");
145. int i = 0;
146. for(SearchBean bean : result) {
147. if(i == 10)
148. break;
149. "bean.name " + bean.getClass().getName() + " : bean.id " + bean.getId()+ " : bean.username " + bean.getUsername());
150. i++;
151. }
152.
153. "searchBean.result.size : " + result.size());
154. Long endTime = System.currentTimeMillis();
155. "查询所花费的时间为:" + (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的博客就无法解析中文字符串!
虽功未成,亦未敢藏私,众侠诸神通尽录于此,竟成一笈,名葵花宝典,以飨后世。