1.1 配置步骤
1.1.1 第一部分:搭建环境(创建项目,导入包)
前提:已经创建好了数据库(直接导入book.sql文件)
* create table `book` ( |
1.1.1.1 第一步:下载Lucene
Lucene是开发全文检索功能的工具包,使用时从官方网站下载,并解压。
官方网站:http://lucene.apache.org/
下载地址:http://archive.apache.org/dist/lucene/java/
下载版本:4.10.3(要求:jdk1.7及以上)
核心包lucene-core-4.10.3.jar(附常用API)
|
1.1.1.2 第二步:创建项目,导入包
mysql5.1驱动包:mysql-connector-java-5.1.7-bin.jar 核心包:lucene-core-4.10.3.jar 分析器通用包:lucene-analyzers-common-4.10.3.jar 查询解析器包:lucene-queryparser-4.10.3.jar |
项目结构如下:
|
1.1.2 第二部分:创建索引
步骤说明:
(1)采集数据
(2)将数据转换成Lucene文档
(3)将文档写入索引库,创建索引
1.1.2.1 第一步:采集数据
Lucene全文检索,不是直接查询数据库,所以需要先将数据采集出来。
(1)创建Book类
public class Book { private Integer bookId; // 图书ID private String name; // 图书名称 private Float price; // 图书价格 private String pic; // 图书图片 private String description; // 图书描述 // 补全get\set方法 } |
(2)创建一个BookDao类
package cn.gzsxt.lucene.dao;
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List;
import cn.gzsxt.lucene.pojo.Book;
public class BookDao { public List<Book> getAll() { // 数据库链接 Connection connection = null; // 预编译statement PreparedStatement preparedStatement = null; // 结果集 ResultSet resultSet = null; // 图书列表 List<Book> list = new ArrayList<Book>(); try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 连接数据库 connection = DriverManager.getConnection( "jdbc:mysql://localhost:3306/lucene", "root", "gzsxt");
// SQL语句 String sql = "SELECT * FROM book"; // 创建preparedStatement preparedStatement = connection.prepareStatement(sql);
// 获取结果集 resultSet = preparedStatement.executeQuery();
// 结果集解析 while (resultSet.next()) { Book book = new Book(); book.setBookId(resultSet.getInt("id")); book.setName(resultSet.getString("name")); book.setPrice(resultSet.getFloat("price")); book.setPic(resultSet.getString("pic")); book.setDescription(resultSet.getString("description")); list.add(book); } } catch (Exception e) { e.printStackTrace();
}finally {
if(null!=resultSet){ try { resultSet.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(null!=preparedStatement){ try { preparedStatement.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(null!=connection){ try { connection.close(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } return list; } } |
(3)创建一个测试类BookDaoTest
package cn.gzsxt.lucene.test;
import java.util.List;
import org.junit.Test; import cn.gzsxt.lucene.dao.BookDao; import cn.gzsxt.lucene.pojo.Book;
public class BookDaoTest {
@Test public void getAll(){ BookDao dao = new BookDao(); List<Book> books = dao.getAll();
for (Book book : books) { System.out.println("图书id:"+book.getBookId()+",图书名称:"+book.getName()); } } } |
(4)测试结果,采集数据成功
|
1.1.2.2 第二步:将数据转换成Lucene文档
Lucene是使用文档类型来封装数据的,所有需要先将采集的数据转换成文档类型。其格式为:
|
修改BookDao,新增一个方法,转换数据
public List<Document> getDocuments(List<Book> books){ // Document对象集合 List<Document> docList = new ArrayList<Document>(); // Document对象 Document doc = null; for (Book book : books) { // 创建Document对象,同时要创建field对象 doc = new Document(); // 根据需求创建不同的Field Field id = new TextField("id", book.getBookId().toString(), Store.YES); Field name = new TextField("name", book.getName(), Store.YES); Field price = new TextField("price", book.getPrice().toString(),Store.YES); Field pic = new TextField("pic", book.getPic(), Store.YES); Field desc = new TextField("description", book.getDescription(), Store.YES); // 把域(Field)添加到文档(Document)中 doc.add(id); doc.add(name); doc.add(price); doc.add(pic); doc.add(desc);
docList.add(doc); } return docList; } |
1.1.2.3 第三步:创建索引库
说明:Lucene是在将文档写入索引库的过程中,自动完成分词、创建索引的。因此创建索引库,从形式上看,就是将文档写入索引库!
修改测试类,新增createIndex方法
@Test public void createIndex(){ try { BookDao dao = new BookDao();
// 分析文档,对文档中的field域进行分词 Analyzer analyzer = new StandardAnalyzer(); // 创建索引 // 1) 创建索引库目录 Directory directory = FSDirectory.open(new File("F:\\lucene\\0719")); // 2) 创建IndexWriterConfig对象 IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST, analyzer); // 3) 创建IndexWriter对象 IndexWriter writer = new IndexWriter(directory, cfg); // 4) 通过IndexWriter对象添加文档对象(document) writer.addDocuments(dao.getDocuments(dao.getAll()));
// 5) 关闭IndexWriter writer.close(); System.out.println("创建索引库成功");
} catch (Exception e) { e.printStackTrace(); } } |
测试结果,创建成功!!!
|
1.1.3 第三部分:搜索索引
1.1.3.1 说明
搜索的时候,需要指定搜索哪一个域(也就是字段),并且,还要对搜索的关键词做分词处理。
1.1.3.2 执行搜索
修改测试类,新增searchDocumentByIndex方法
@Test public void searchDocumentByIndex(){ try { // 1、 创建查询(Query对象) // 创建分析器 Analyzer analyzer = new StandardAnalyzer(); QueryParser queryParser = new QueryParser("name", analyzer); Query query = queryParser.parse("name:java教程"); // 2、 执行搜索 // a) 指定索引库目录 Directory directory = FSDirectory.open(new File("F:\\lucene\\0719")); // b) 创建IndexReader对象 IndexReader reader = DirectoryReader.open(directory); // c) 创建IndexSearcher对象 IndexSearcher searcher = new IndexSearcher(reader); // d) 通过IndexSearcher对象执行查询索引库,返回TopDocs对象 // 第一个参数:查询对象 // 第二个参数:最大的n条记录 TopDocs topDocs = searcher.search(query, 10); // e) 提取TopDocs对象中前n条记录 ScoreDoc[] scoreDocs = topDocs.scoreDocs; System.out.println("查询出文档个数为:" + topDocs.totalHits); for (ScoreDoc scoreDoc : scoreDocs) { // 文档对象ID int docId = scoreDoc.doc; Document doc = searcher.doc(docId); // f) 输出文档内容 System.out.println("==============================="); System.out.println("文档id:" + docId); System.out.println("图书id:" + doc.get("id")); System.out.println("图书name:" + doc.get("name")); System.out.println("图书price:" + doc.get("price")); System.out.println("图书pic:" + doc.get("pic")); System.out.println("图书description:" + doc.get("description")); } // g) 关闭IndexReader reader.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } |
测试结果,非常成功!!!
|
1.2 小结
Lucene全文检索,确实可以实现对关键词做分词、再执行搜索功能。并且结果更精确。