1.Lucene简介
Lucene是一个开源的全文检索引擎工具包,它提供了完整的索引引擎、查询引擎和部分文本分析引擎。Lucene为软件开发人员提供了一套简单易用的检索引擎开发工具包,以便在系统中实现全文检索功能,或者以Lucene为基础建立一套完整的全文检索引擎。
全文搜索引擎的工作原理:扫描问答库中的每一条记录并分词建立索引,索引记录了词在每一条问答记录中出现的次数和位置,当收到用户的问题时,也会对问题进行分词,然后从索引中找出包含这些词的所有回答记录,再分别计算这些问答记录与用户问题的相似度,找出相似度最高的一条回答记录返回给用户。
Lucene的优点:索引文件格式独立于应用平台、高效的索引引擎、强大的查询引擎、易扩展。
2.Lucene索引和检索原理
Lucene能够对任何数据做索引和检索,像txt、word、pdf、数据库等格式的数据源,我们都可以通过其他工具或编程方式将这些格式的数据读取出来,转化为文本形式的数据,这样就能使用Lucene对这些文本数据建立索引以及做检索。
3.Lucene索引和检索数据库
1.创建JDBC获取Connection工具类
package com.tgb.org; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; /** * JDBC获取Connection工具类 * @author quwenzhe * */ public class JdbcUtil { private static Connection conn = null; private static final String URL = "jdbc:mysql://localhost:3306/lucene"; private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; private static final String USER_NAME = "root"; private static final String PASSWORD = "root"; 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; } }
2.创建JavaBean类
package com.tgb.org; public class UserInfo { private String id; private String username; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } }
3.对数据库信息创建索引并对索引进行检索
package com.tgb.org; import java.io.File; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; import org.wltea.analyzer.lucene.IKAnalyzer; public class SearchLogic { private static Connection conn = null; private static Statement stmt = null; private static ResultSet rs = null; // 索引保存目录 private String indexDir = "D:\\lucence\\index2"; private static IndexSearcher searcher = null; //创建分词器 private static Analyzer analyzer = new IKAnalyzer(true); /** * 获取数据库数据 * @param queryStr 需要检索的关键字 * @return * @throws Exception */ public List<UserInfo> getResult(String queryStr) throws Exception { List<UserInfo> result = null; conn = JdbcUtil.getConnection(); if (conn == null) { throw new Exception("数据库连接失败!"); } String sql = "select id, username from t_user"; try { stmt = conn.createStatement(); rs = stmt.executeQuery(sql); // 给数据库创建索引,此处执行一次,不要每次运行都创建索引 // 以后数据有更新可以后台调用更新索引 this.createIndex(rs); TopDocs topDocs = this.search(queryStr); ScoreDoc[] scoreDocs = topDocs.scoreDocs; result = this.addHits2List(scoreDocs); } catch (Exception e) { e.printStackTrace(); throw new Exception("数据库查询sql出错! sql : " + sql); } finally { if (rs != null) rs.close(); if (stmt != null) stmt.close(); if (conn != null) conn.close(); } return result; } /** * 为数据库检索数据创建索引 * @param 访问数据库返回的ResultSet * @throws Exception */ private void createIndex(ResultSet rs) throws Exception { // 创建或打开索引 Directory directory = FSDirectory.open(new File(indexDir)); // 创建IndexWriter IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_46, analyzer); IndexWriter indexWriter = new IndexWriter(directory, conf); // 遍历ResultSet创建索引 while (rs.next()) { // 创建document并添加field Document doc = new Document(); doc.add(new TextField("id", rs.getString("id"), Field.Store.YES)); doc.add(new TextField("username", rs.getString("username"), Field.Store.YES)); // 将doc添加到索引中 indexWriter.addDocument(doc); } indexWriter.commit(); indexWriter.close(); directory.close(); } /** * 检索索引 * @param queryStr 需要检索的关键字 * @return * @throws Exception */ private TopDocs search(String queryStr) throws Exception { //创建或打开索引目录 Directory directory = FSDirectory.open(new File(indexDir)); IndexReader reader = IndexReader.open(directory); if (searcher == null) { searcher = new IndexSearcher(reader); } //使用查询解析器创建Query QueryParser parser = new QueryParser(Version.LUCENE_46, "username", analyzer); Query query = parser.parse(queryStr); //从索引中搜索得到排名前10的文档 TopDocs topDocs = searcher.search(query, 10); return topDocs; } /** * 将检索结果添加到List中 * @param scoreDocs * @return * @throws Exception */ private List<UserInfo> addHits2List(ScoreDoc[] scoreDocs) throws Exception { List<UserInfo> listBean = new ArrayList<UserInfo>(); UserInfo bean = null; for (int i = 0; i < scoreDocs.length; i++) { int docId = scoreDocs[i].doc; Document doc = searcher.doc(docId); bean = new UserInfo(); bean.setId(doc.get("id")); bean.setUsername(doc.get("username")); listBean.add(bean); } return listBean; } public static void main(String[] args) { SearchLogic logic = new SearchLogic(); try { Long startTime = System.currentTimeMillis(); List<UserInfo> result = logic.getResult("屈文哲"); int i = 0; for (UserInfo bean : result) { if (i == 10) break; System.out.println("bean.name " + bean.getClass().getName() + " : bean.id " + bean.getId() + " : bean.username " + bean.getUsername()); i++; } System.out.println("searchBean.result.size : " + result.size()); Long endTime = System.currentTimeMillis(); System.out.println("查询所花费的时间为:" + (endTime - startTime) / 1000); } catch (Exception e) { e.printStackTrace(); System.out.println(e.getMessage()); } } }
项目依赖的jar:
看完上述代码我们可以发现,Lucene对访问数据库的返回值ResultSet建立索引,然后通过对索引进行检索,检索出符合条件的数据,从而提高对数据库的查询效率。
时间: 2024-10-12 16:56:44