JAVA_WEB專案之Lucene檢索框架入門案例
web開發中一般會碰到查詢資料到前臺顯示,對於較低要求的專案可以用like檢索每次檢索資料庫,但是非常消耗資料庫資源,因此我們可以使用Lucene檢索框架來解決查詢效率的問題。下面直接用程式碼貼出個人學習的案例:
開始前先下載lucene3.0的5個jar包:
1、IKAnalyzer3.2.8.jar分詞器包
2、lucene-analyzers-3.0.0.jar分詞器包
3、lucene-core-3.0.0.jar核心包
4、lucene-highlighter-3.0.0.jar高亮包
5、lucene-memory-3.0.0.jar
首先定義一個實體類:Goods
package com.shop.demo;
public class Goods {
private Integer id;
private String name;
private Double price;
private String pic;
private String remark;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
接下來定義一個HelloWordLucene:
package com.shop.demo;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.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;
/**
* 此案例實現Lucene向索引庫中新增索引和查詢索引的功能
* @author Administrator
*
*/
public class HelloWordLucene {
/**
* 把good商品物件新增到索引庫中
* @param goods
*/
public void addDocument(Goods goods){
//建立indexWriter
IndexWriter indexwriter=null;
//建立索引庫
Directory dir=null;
//建立分詞器
Analyzer ana=null;
try {
//根據指定的路徑建立索引庫,如果路徑不存在就會建立
dir=FSDirectory.open(new File("c:/demo"));
//不同的分詞器的版本不同,分詞的演算法不同,StandardAnalyzer只適用於英文
ana=new StandardAnalyzer(Version.LUCENE_30);
//限制Field的數量為10000
indexwriter=new IndexWriter(dir, ana, MaxFieldLength.LIMITED);
//把goods物件轉為document
Document doc=new Document();
/**
* Store配置field欄位是否儲存到索引庫
* YES:欄位儲存到索引庫中,以後查詢的時候可以查詢出來
* No:不儲存到索引庫中
* Index: Lucene為提高查詢效率,會像字典一樣建立索引. 配置此欄位是否要建立索引(建立索引的Field就是Term),
* 如果建立索引以後就可以通過此欄位查詢記錄
* NOT_ANALYZED: 建立索引,但是Field的不分詞(不分開) 整體作為一個索引
* ANALYZED: 不但要建立索引此Field會被分詞(可能一個Field分為多個Term的情況)
* NO: 不建立索引,以後不能通過此欄位查詢資料
* Store yes Index: ANALYZED: 此Field可以儲存,而且Field 關鍵字支援分詞
* Store yes Index: NOT_ANALYZED 此Field可以儲存,但是Field不支援分詞,作為一個完成Term 例如: 數字 id price 和URL 專業詞彙
* Store yes Index: NO: 可以查詢出此欄位, 但是此欄位不作為查詢關鍵字
* Store no Index: ANALYZED: 此Field不儲存,但是此Field可以做為關鍵字搜尋
* Store no Index: NOT_ANALYZED: 此Field不儲存,但是此Field可以做為整體(不拆分)關鍵字搜尋
* Store no Index: NO: 既不建索引也不儲存 沒有任何意義,如果這樣配置則會丟擲異常
*/
doc.add(new Field("id", goods.getId().toString(), Store.YES, Index.NOT_ANALYZED));
doc.add(new Field("name", goods.getName(), Store.YES, Index.ANALYZED));
doc.add(new Field("price", goods.getPrice().toString(), Store.YES, Index.NOT_ANALYZED));
doc.add(new Field("remark", goods.getRemark(), Store.NO, Index.ANALYZED));
indexwriter.addDocument(doc);
// 如果沒有提交,在沒有異常的情況close()之前會自動提交
indexwriter.commit();
} catch (Exception e) {
try {
indexwriter.rollback();
throw new RuntimeException(e);
} catch (IOException e1) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}finally{
try {
indexwriter.close();
} catch (Exception e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
}
/**
* 根據指定的條件查詢,
* @param name 指定的關鍵字
* @return 封裝了goods物件的list集合
*/
public List<Goods> queryGoods(String name){
List<Goods> goodsList=new ArrayList<Goods>();
//建立查詢物件
IndexSearcher searcher=null;
//建立索引庫
Directory dir=null;
//建立分詞器
Analyzer analyzer=null;
try {
dir=FSDirectory.open(new File("c:/demo"));
searcher=new IndexSearcher(dir);
// 建立分詞器,給查詢的關鍵字先做分詞操作,然後在到索引庫中匹配Term
analyzer=new StandardAnalyzer(Version.LUCENE_30);
//建立查詢解析物件,"name"指定從索引庫中的哪個field屬性裡面查詢,也就是name到那個Term(key value)中去查詢
QueryParser queryParser=new QueryParser(Version.LUCENE_30, "name", analyzer);
// 指定查詢的關鍵字到索引庫查詢
Query query=queryParser.parse(name);
/**
* 根據給定的關鍵字查詢,與索引庫Term去匹配,5代表: 期望返回的結果數
* 第一次查詢: indexSearcher.search 只能獲取文件的索引號和匹配的數量
* 返回的結果是TopDoc型別
* totalHits: 命中數, 陣列的長度,後面用來做分頁
* ScoreDoc[]: 儲存匹配的文件編號的陣列
* Score: 文件的積分,按照命中率自動算出來
* Doc:當前文件的編號
*/
TopDocs topDocs= searcher.search(query, 5);
// 此變數/每頁顯示的記錄數就是總頁數
System.out.println("真正命中的結果數:" + topDocs.totalHits);
// 返回的是符合條件的文件編號,並不是文件本事
ScoreDoc scoreDocs[]= topDocs.scoreDocs;
for(int i=0;i<scoreDocs.length;i++){
ScoreDoc scoreDoc= scoreDocs[i];
System.out.println("真正的命中率:"+scoreDoc.score);
System.out.println("儲存的是文件編號:"+scoreDoc.doc);
Document doc= searcher.doc(scoreDoc.doc);
System.out.println(doc.get("id"));
System.out.println(doc.get("name"));
System.out.println(doc.get("price"));
System.out.println(doc.get("remark"));
System.out.println("---------");
Goods goods=new Goods();
goods.setId(Integer.parseInt(doc.get("id")));
goods.setName(doc.get("name"));
goods.setPrice(Double.parseDouble(doc.get("price")));
goods.setRemark(doc.get("remark"));
goodsList.add(goods);
}
} catch (Exception e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}finally{
try {
searcher.close();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
return goodsList;
}
}
接下寫測試用例:
package com.shop.demo;
import java.util.List;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class HelloWordLuceneTest {
private static HelloWordLucene hellowod;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
hellowod=new HelloWordLucene();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
hellowod=null;
}
@Test
public void testAddDocument() {
Goods goods=new Goods();
goods.setId(13);
goods.setName("IBM Computer1112 IBM");
goods.setPrice(2333.9);
goods.setRemark("IBM Computer is good");
hellowod.addDocument(goods);
}
@Test
public void testquery() {
List<Goods> list= hellowod.queryGoods("ibm");
for(Goods good:list){
System.out.println("商品編號:"+good.getId()+",商品名稱:"+good.getName()+
",商品價格:"+good.getPrice()+",商品的詳細資訊:"+good.getRemark()
);
}
}
}
結果顯示:
真正命中的結果數:5
真正的命中率:0.578186
儲存的是文件編號:4
13
IBM Computer1112 IBM
2333.9
null
---------
真正的命中率:0.51104903
儲存的是文件編號:0
11
IBM Computer
2333.9
null
---------
真正的命中率:0.51104903
儲存的是文件編號:1
11
IBM Computer22
2333.9
null
---------
真正的命中率:0.51104903
儲存的是文件編號:2
12
IBM Computer22
2333.9
null
---------
真正的命中率:0.51104903
儲存的是文件編號:3
13
IBM Computer1112
2333.9
null
---------
商品編號:13,商品名稱:IBM Computer1112 IBM,商品價格:2333.9,商品的詳細資訊:null
商品編號:11,商品名稱:IBM Computer,商品價格:2333.9,商品的詳細資訊:null
商品編號:11,商品名稱:IBM Computer22,商品價格:2333.9,商品的詳細資訊:null
商品編號:12,商品名稱:IBM Computer22,商品價格:2333.9,商品的詳細資訊:null
商品編號:13,商品名稱:IBM Computer1112,商品價格:2333.9,商品的詳細資訊:null
相關文章
- 全文檢索技術lucene的demo
- 基於Lucene的全文檢索實踐
- Lucene可以對MYSQL進行全文檢索嗎?MySql
- JAVA_WEB專案之Action層利用ModelDriven抽取BaseActionJavaWeb
- lucene學習總結篇--lucene全文檢索的基本原理和lucene API簡單的使用API
- ElasticSearch入門檢索Elasticsearch
- JAVA_WEB專案之j使用query的驗證框架的例子JavaWeb框架
- 讀書筆記:從Lucene到Elasticsearch:全文檢索實戰筆記Elasticsearch
- Newbe.Claptrap 框架入門,第二步 —— 建立專案APT框架
- ABP框架入門框架
- Flask框架入門Flask框架
- Lucene--專案記錄(1)
- J.U.C之Executor框架入門指引框架
- flask專案之圖書案例Flask
- 專案管理之風險管理案例-專案交付風險專案管理
- ElasticSearch 億級資料檢索案例實戰Elasticsearch
- SpringMVC框架入門SpringMVC框架
- Spring框架入門Spring框架
- Play框架入門使用框架
- DWR框架入門例子框架
- Oracle全文檢索之Ctxcat 索引Oracle索引
- Oracle全文檢索之ContextOracleContext
- lucene入門使用
- Java Mybatis 框架入門教程JavaMyBatis框架
- CppUnit測試框架入門框架
- SQL Server之查詢檢索操作SQLServer
- 一種基於概率檢索模型的大資料專利檢索方法與流程模型大資料
- 擊敗二分檢索演算法——插值檢索、快速檢索演算法
- lucene入門問題
- Casbin訪問控制框架入門框架
- immy框架入門系列(2)——class框架
- 影象處理入門:目標檢測和影象檢索綜述
- 資訊檢索
- BLOG - 個人博文系統開發總結 二:使用Lucene完成博文檢索功能
- 請教一個使用lucene做全文檢索與資料庫連線時的問題資料庫
- 影象檢索:資訊檢索評價指標mAP指標
- Newbe.Claptrap 框架入門,第一步 —— 建立專案,實現簡易購物車APT框架
- 資訊檢索與排序模型之布林模型排序模型