Lucene入門程式, 詳細示範了如何通過Maven建構第一個Lucene程式, 并對其Java API的簡單使用作了說明. 另外, 對Luke工具的簡單使用作了示例.
目錄
- 1 準備環境
- 2 準備資料
- 3 建立工程
- 3.1 建立Maven Project(打包方式選jar即可)
- 3.2 配置pom.xml, 導入依賴
- 4 編寫基礎代碼
- 4.1 編寫圖書POJO
- 4.2 編寫圖書DAO接口
- 4.3 實作圖書DAO接口
- 5 索引流程的實作
- 5.1 示例代碼
- 5.2 測試結果
- 6 使用Luke工具檢視索引
- 6.1 使用說明
- 6.2 運作界面一
- 6.3 運作界面二
- 6.4 運作界面三
- 7 檢索流程的實作
- 7.1 使用Luke工具搜尋
- 7.2 示例代碼
- 7.3 測試結果
- 7.4 結果說明
- 7.5 IndexSearcher方法
- 版權聲明
JDK: 1.8.0_162
IDE: Eclipse Neon.3
資料庫: MySQL 5.7.20
Lucene: 4.10.4(已經很穩定了,高版本對部分分詞器支援不好)
SET FOREIGN_KEY_CHECKS=0;
--------------------------------
Table structure for `book`
--------------------------------
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book` (
`id` int(11) DEFAULT NULL,
`bookname` varchar(500) DEFAULT NULL,
`price` float DEFAULT NULL,
`pic` varchar(200) DEFAULT NULL,
`bookdesc` varchar(2000) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--------------------------------
Records of book
--------------------------------
INSERT INTO `book` VALUES ('1', 'java從入門到精通', '56', '1.jpg', '《Java從入門到精通》是人民郵電出版社于 2010年出版的圖書, 由國家863中部軟體孵化器主編. 以零基礎講解為宗旨, 深入淺出地講解Java的各項技術及實戰技能. 本書從初學者角度出發, 通過通俗易懂的語言、豐富多彩的執行個體, 詳細介紹了使用Java語言進行程式開發應該掌握的各方面技術.');
INSERT INTO `book` VALUES ('2', 'java web開發', '80', '2.jpg', 'Java Web, 是用Java技術來解決相關web網際網路領域的技術總和. web包括: web伺服器和web用戶端兩部分. Java在用戶端的應用有java applet, 不過使用得很少, Java在伺服器端的應用非常的豐富, 比如Servlet, JSP和第三方架構等等. Java技術對Web領域的發展注入了強大的動力. ');
INSERT INTO `book` VALUES ('3', 'lucene從入門到精通', '100', '3.jpg', '本書總結搜尋引擎相關理論與實際解決方案, 并給出了 Java 實作, 其中利用了流行的開源項目Lucene和Solr, 而且還包括原創的實作. 本書主要包括總體介紹部分、爬蟲部分、自然語言處理部分、全文檢索部分以及相關案例分析. 爬蟲部分介紹了網頁周遊方法和如何實作增量抓取, 并介紹了從網頁等各種格式的文檔中提取主要内容的方法.');
INSERT INTO `book` VALUES ('4', 'lucene in action', '90', '4.jpg', '本書深入淺出地介紹了lucene——一個開源的使用java語言編寫的全文搜尋引擎開發包. 它通過淺顯的語言、大量的圖注、豐富的代碼示例, 以及清晰的結構為讀者呈現出作為優秀開源項目的lucene所展現的強大功能. ');
INSERT INTO `book` VALUES ('5', 'Lucene Java精華版', '80', '5.jpg', '本書總結搜尋引擎相關理論與實際解決方案, 并給出了 Java 實作, 其中利用了流行的開源項目Lucene和Solr, 而且還包括原創的實作. 本書主要包括總體介紹部分、爬蟲部分、自然語言處理部分、全文檢索部分以及相關案例分析. 爬蟲部分介紹了網頁周遊方法和如何實作增量抓取, 并介紹了從網頁等各種格式的文檔中提取主要内容的方法. ');

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.healchow</groupId>
<artifactId>lucene-first</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>lucene-first</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- mysql版本 -->
<mysql.version>5.1.44</mysql.version>
<!-- lucene版本 -->
<lucene.version>4.10.4</lucene.version>
</properties>
<dependencies>
<!-- mysql資料庫依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- lucene依賴包 -->
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
public class Book {
private Integer id; // int(11) DEFAULT NULL,
private String bookname; // varchar(500) DEFAULT NULL,
private Float price; // float DEFAULT NULL,
private String pic; // varchar(200) DEFAULT NULL,
private String bookdesc; // varchar(2000) DEFAULT NULL
// Getters/Setters
@Override
public String toString() {
return "Book [id=" + id + ", bookname=" + bookname +
", price=" + price + ", pic=" + pic +
", bookdesc=" + bookdesc + "]";
}
}
public interface BookDao {
/**
* 查詢全部圖書
*/
List<Book> queryBookList();
}
public class BookDaoImpl implements BookDao {
/**
* 查詢全部圖書
*/
public List<Book> listAll() {
// 建立圖書結果集合List
List<Book> books = new ArrayList<Book>();
Connection conn = null;
PreparedStatement preStatement = null;
ResultSet resultSet = null;
try {
// 加載驅動
Class.forName("com.mysql.jdbc.Driver");
// 建立資料庫連接配接對象
conn = DriverManager.getConnection(
"jdbc:mysql://127.0.0.1:3306/lucene?useSSL=true",
"root",
"password");
// 定義查詢SQL
String sql = "select * from book";
// 建立Statement語句對象
preStatement = conn.prepareStatement(sql);
// 執行語句, 得到結果集
resultSet = preStatement.executeQuery();
// 處理結果集
while (resultSet.next()) {
// 建立圖書對象
Book book = new Book();
book.setId(resultSet.getInt("id"));
book.setBookname(resultSet.getString("bookname"));
book.setPrice(resultSet.getFloat("price"));
book.setPic(resultSet.getString("pic"));
book.setBookdesc(resultSet.getString("bookdesc"));
// 将查詢到的結果添加到list中
books.add(book);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 釋放資源
try {
if (null != conn) conn.close();
if (null != preStatement) preStatement.close();
if (null != resultSet) resultSet.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return books;
}
/**
* 測試功能的主方法
*/
public static void main(String[] args) {
// 建立圖書Dao的實作對象
BookDao bookDao = new BookDaoImpl();
List<Book> books = bookDao.listAll();
// 如果結果不為空, 則便利輸出
for (Book book : books) {
System.out.println(book);
}
}
}
測試結果如下:
(1) 采集原始資料;
(2) 建立文檔對象(Document);
(3) 建立分析器對象(Analyzer), 用于分詞;
(4) 建立索引配置對象(IndexWriterConfig), 用于配置Lucene;
(5) 建立索引庫目錄位置對象(Directory), 指定索引庫的存儲位置;
(6) 建立索引寫入對象(IndexWriter), 将文檔對象寫入索引庫;
(7) 使用IndexWriter對象, 建立索引;
(8) 釋放資源.
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
public class IndexManager {
/**
* 建立索引功能的測試
* @throws Exception
*/
@Test
public void createIndex() throws IOException{
// 1. 采集資料
BookDao bookDao = new BookDaoImpl();
List<Book> books = bookDao.listAll();
// 2. 建立文檔對象
List<Document> documents = new ArrayList<Document>();
for (Book book : books) {
Document document = new Document();
// 給文檔對象添加域
// add方法: 把域添加到文檔對象中, field參數: 要添加的域
// TextField: 文本域, 屬性name:域的名稱, value:域的值, store:指定是否将域值儲存到文檔中
document.add(new TextField("bookId", book.getId() + "", Store.YES));
document.add(new TextField("bookName", book.getBookname(), Store.YES));
document.add(new TextField("bookPrice", book.getPrice() + "", Store.YES));
document.add(new TextField("bookPic", book.getPic(), Store.YES));
document.add(new TextField("bookDesc", book.getBookdesc(), Store.YES));
// 将文檔對象添加到文檔對象集合中
documents.add(document);
}
// 3. 建立分析器對象(Analyzer), 用于分詞
Analyzer analyzer = new StandardAnalyzer();
// 4. 建立索引配置對象(IndexWriterConfig), 用于配置Lucene
// 參數一:目前使用的Lucene版本, 參數二:分析器
IndexWriterConfig indexConfig = new IndexWriterConfig(Version.LUCENE_4_10_2, analyzer);
// 5. 建立索引庫目錄位置對象(Directory), 指定索引庫的存儲位置
File path = new File("/your_path/index");
Directory directory = FSDirectory.open(path);
// 6. 建立索引寫入對象(IndexWriter), 将文檔對象寫入索引
IndexWriter indexWriter = new IndexWriter(directory, indexConfig);
// 7. 使用IndexWriter對象建立索引
for (Document doc : documents) {
// addDocement(doc): 将文檔對象寫入索引庫
indexWriter.addDocument(doc);
}
// 8. 釋放資源
indexWriter.close();
}
}
說明: 隻要看到以下檔案, 說明索引已經建立成功了:
Windows OS下,輕按兩下運作start.bat檔案(前提是需要配置jdk的環境變量);
Mac OS下, 在終端中進入目前目錄, 然後鍵入 ./start.sh 即可運作.
(1) 建立分析器對象(Analyzer), 用于分詞;
(2) 建立查詢對象(Query);
(3) 建立索引庫目錄位置對象(Directory), 指定索引庫的位置;
(4) 建立索引讀取對象(IndexReader), 用于讀取索引;
(5) 建立索引搜尋對象(IndexSearcher), 用于執行搜尋;
(6) 使用IndexSearcher對象, 執行搜尋, 傳回搜尋結果集TopDocs;
(7) 處理結果集;
bookName:lucene
—— 表示搜尋bookName域中包含有lucene.
/**
* 檢索索引功能的測試
* @throws Exception
*/
@Test
public void searchIndexTest() throws Exception {
// 1. 建立分析器對象(Analyzer), 用于分詞
Analyzer analyzer = new StandardAnalyzer();
// 2. 建立查詢對象(Query)
// 2.1 建立查詢解析器對象
// 參數一:預設的搜尋域, 參數二:使用的分析器
QueryParser queryParser = new QueryParser("bookName", analyzer);
// 2.2 使用查詢解析器對象, 執行個體化Query對象
Query query = queryParser.parse("bookName:lucene");
// 3. 建立索引庫目錄位置對象(Directory), 指定索引庫位置
Directory directory = FSDirectory.open(new File("/your_path/index"));
// 4. 建立索引讀取對象(IndexReader), 用于讀取索引
IndexReader indexReader = DirectoryReader.open(directory);
// 5. 建立索引搜尋對象(IndexSearcher), 用于執行索引
IndexSearcher searcher = new IndexSearcher(indexReader);
// 6. 使用IndexSearcher對象執行搜尋, 傳回搜尋結果集TopDocs
// 參數一:使用的查詢對象, 參數二:指定要傳回的搜尋結果排序後的前n個
TopDocs topDocs = searcher.search(query, 10);
// 7. 處理結果集
// 7.1 列印實際查詢到的結果數量
System.out.println("實際查詢到的結果數量: " + topDocs.totalHits);
// 7.2 擷取搜尋的結果數組
// ScoreDoc中有文檔的id及其評分
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
System.out.println("= = = = = = = = = = = = = = = = = = =");
// 擷取文檔的id和評分
int docId = scoreDoc.doc;
float score = scoreDoc.score;
System.out.println("文檔id= " + docId + " , 評分= " + score);
// 根據文檔Id, 查詢文檔資料 -- 相當于關系資料庫中根據主鍵Id查詢資料
Document doc = searcher.doc(docId);
System.out.println("圖書Id: " + doc.get("bookId"));
System.out.println("圖書名稱: " + doc.get("bookName"));
System.out.println("圖書價格: " + doc.get("bookPrice"));
System.out.println("圖書圖檔: " + doc.get("bookPic"));
System.out.println("圖書描述: " + doc.get("bookDesc"));
}
// 8. 關閉資源
indexReader.close();
}
(1) 索引庫中包含索引域和文檔域;
(2) 索引域儲存索引資料(反向索引), 用于索引;
(3) 文檔域中儲存文檔資料, 用于搜尋擷取資料.
方法 | 說明 |
---|---|
indexSearcher.search(query, n) | 根據Query搜尋, 傳回評分最高的n條記錄 |
indexSearcher.search(query,filter,n) | 根據Query搜尋, 添加過濾政策, 傳回評分最高的n條記錄 |
indexSearcher.search(query, n, sort) | 根據Query搜尋, 添加排序政策, 傳回評分最高的n條記錄 |
indexSearcher.search(booleanQuery, filter, n, sort) | 根據Query搜尋, 添加過濾政策, 添加排序政策, 傳回評分最高的n條記錄 |
作者: 馬瘦風
出處: 部落格園 馬瘦風的部落格
您的支援是對部落客的極大鼓勵, 感謝您的閱讀.
本文版權歸部落客所有, 歡迎轉載, 但請保留此段聲明, 并在文章頁面明顯位置給出原文連結, 否則部落客保留追究相關人員法律責任的權利.