1.1 需求
使用Lucene實現電商項目中圖書類商品的索引和搜索功能。
1.2 配置步驟說明
(1)搭建環境(先下載Lucene)
(2)創建索引庫
(3)搜索索引庫
1.3 配置步驟
1.3.1 第一部分:搭建環境(創建項目,導入包)
前提:已經創建好了數據庫(直接導入book.sql文件)
|
1.3.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.3.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.3.2 第二部分:創建索引
步驟說明:
(1)采集數據
(2)將數據轉換成Lucene文檔
(3)將文檔寫入索引庫,創建索引
1.3.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.lxm.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.lxm.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", "111");
// 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.lxm.lucene.test;
import java.util.List;
import org.junit.Test; import cn.lxm.lucene.dao.BookDao; import cn.lxm.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.3.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.3.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("D:\\A")); // 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.3.3 第三部分:搜索索引
1.3.3.1 說明
搜索的時候,需要指定搜索哪一個域(也就是字段),並且,還要對搜索的關鍵詞做分詞處理。
1.3.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("D:\\A")); // 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(); } } |
測試結果,非常成功!!!
![]()
|