一楞抡、說明
在實(shí)際開發(fā)中,由于開啟IndexReader
和IndexWriter
這兩個(gè)對(duì)象很消耗資源析藕,所以一般會(huì)使用單例召廷,或者不關(guān)閉而使用一個(gè)池,對(duì)應(yīng)于數(shù)據(jù)庫的會(huì)話一樣账胧。
二竞慢、單例 IndexReader
這里我們還是拷貝工程lucene_index02
為lucene_index03
,在之前工程的基礎(chǔ)上進(jìn)行改進(jìn)治泥。
- 在
IndexUtil.java
類中我們聲明一個(gè)IndexReader
的屬性:
private static IndexReader reader = null;//聲明一個(gè)IndexReader的屬性
- 然后改進(jìn)方法
IndexUtil()
:
public IndexUtil() {
try {
setDates();//設(shè)置日期
scores.put("qq.com", 2.0f);//如果是"qq.com"結(jié)尾的索引則讓其權(quán)值為2.0筹煮,注意:默認(rèn)是1.0
scores.put("sina.edu", 1.5f);
directory = FSDirectory.open(new File("E:/myeclipse/Lucene/index"));
reader = IndexReader.open(directory);//在工具一創(chuàng)建的時(shí)候就打開IndexReader
} catch (IOException e) {
e.printStackTrace();
}
}
在構(gòu)造方法中我們實(shí)例化IndexReader
,這樣就達(dá)到了單例的效果居夹。
- 定義一個(gè)方法獲取
IndexSearcher
類:
public IndexSearcher getSearcher(){
return new IndexSearcher(reader);
}
- 改進(jìn)搜索方法:
public void search02(){
IndexReader reader;
try {
IndexSearcher searcher = getSearcher();
TermQuery query = new TermQuery(new Term("content", "like"));//搜索內(nèi)容中含有l(wèi)ike的
TopDocs tds = searcher.search(query, 10);
for(ScoreDoc sd : tds.scoreDocs){
Document doc = searcher.doc(sd.doc);
//這里我們獲取權(quán)值getBoost()的時(shí)候發(fā)現(xiàn)都是1.0败潦,這是因?yàn)檫@里是獲取的一個(gè)document,和原來的沒有關(guān)系吮播。
//要想看其權(quán)值信息,可以使用luke工具
//而這里的日期需要我們轉(zhuǎn)換成日期格式
System.out.println("id號(hào):" + doc.get("id")
+ "眼俊,權(quán)值:"+ doc.getBoost()
+ "意狠,名字:" + doc.get("name")
+ ",郵箱:" + doc.get("email")
+ "疮胖,附件條數(shù):" +doc.get("attach")
+ "环戈,日期:" + doc.get("date"));
searcher.close();//注意:這里不是關(guān)閉reader闷板,而是關(guān)閉searcher
}
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
注意:這里我們就不要關(guān)閉reader
了,而是關(guān)閉searcher
院塞,這樣reader
就可以一直使用一個(gè)遮晚。
- 測(cè)試
@Test
public void testSearch02(){
IndexUtil util = new IndexUtil();
for(int i = 0; i < 5; i++){
util.search02();//這里我們讓其執(zhí)行5次
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
說明:這里我們?cè)跍y(cè)試的時(shí)候先重新生成索引,然后使用上面的測(cè)試方法測(cè)試拦止,我們每個(gè)10秒執(zhí)行一次搜索县遣,在搜索的過程中,我們?cè)龠\(yùn)行刪除方法汹族,刪除id
為1的索引萧求,但是我們發(fā)現(xiàn)即使刪除了,索引卻并沒有變少顶瞒,這是因?yàn)槲覀円恢笔褂玫氖峭粋€(gè)reader
夸政。但是當(dāng)我們關(guān)閉此測(cè)試方法,再使用之前的搜索方法testSearch01
測(cè)試一下榴徐,發(fā)現(xiàn)索引少了一條守问,針對(duì)此問題,我們繼續(xù)改進(jìn)坑资。
- 改進(jìn)
getSearcher
方法
public IndexSearcher getSearcher(){
try {
if(reader == null){
reader = IndexReader.open(directory);
}else{
//如果reader發(fā)生改變則返回舊的reader耗帕,否則創(chuàng)建一個(gè)新的reader
IndexReader tr = IndexReader.openIfChanged(reader);
if(tr != null){
reader.close();//關(guān)閉舊的reader
reader = tr;
}
}
return new IndexSearcher(reader);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
說明:這里我們使用方法openIfChanged
,此方法在reader
發(fā)生變化的時(shí)候就會(huì)返回新的reader
盐茎,否則返回舊的reader
兴垦。但是一定注意:我們產(chǎn)生新的reader
之后需要將舊的reader
關(guān)閉。之后我們?cè)谶\(yùn)行上面的測(cè)試方法過程中使用刪除方法會(huì)發(fā)現(xiàn)索引可以實(shí)時(shí)更新了字柠。
三探越、單例 IndexWriter
對(duì)于也是類似,我們拿刪除方法來說明:
public void delete(){
IndexWriter writer = null;
try {
writer = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
//參數(shù)可以是一個(gè)選項(xiàng)窑业,可以是一個(gè)query钦幔,也可以是一個(gè)term,term是一個(gè)精確查找的值
//這里我們測(cè)試此方法之后再次執(zhí)行搜索方法常柄,發(fā)現(xiàn)文檔數(shù)numDocs還有5個(gè)鲤氢,比之前少了一個(gè),但是maxDoc還是6個(gè)
//在我們的索引目錄中發(fā)現(xiàn)出現(xiàn)了一個(gè)delete的文件西潘。這里的刪除就像一個(gè)回收站一樣卷玉,是可以恢復(fù)的
writer.deleteDocuments(new Term("id", "1"));//這里表示刪除索引為1的id
writer.commit();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}/*finally{
if(writer != null){
try {
writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}*/
}
這里我們可以不關(guān)閉IndexWriter
,但是如果這樣數(shù)據(jù)就不能實(shí)時(shí)更新喷市,此時(shí)我們可以像數(shù)據(jù)庫那樣相种,提交一下即可。
最后:這里只是簡(jiǎn)單演示的了一下單例品姓,但是例子并不完善寝并,比如這里IndexReader
確實(shí)是在構(gòu)造函數(shù)中實(shí)例化箫措,是單例的,但是我們?cè)趯?duì)創(chuàng)建索引方法測(cè)試的時(shí)候也會(huì)創(chuàng)建一個(gè)IndexReader
對(duì)象衬潦,但是最后卻沒有關(guān)閉斤蔓,不知道是否是這個(gè)原因?qū)е挛覀儨y(cè)試創(chuàng)建對(duì)象方法的時(shí)候出現(xiàn)異常,留待后面解決镀岛。
具體的單例實(shí)現(xiàn)請(qǐng)參考:http://www.cnblogs.com/likehua/archive/2012/02/20/2359087.html
弦牡。