像百度,京東,淘寶一樣的搜索功能使用Lucene實現電商項目中圖書類商品的索引和搜索功能的入門示例


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();

}

}

測試結果,非常成功!!!

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM