lucene4之後的近實時搜索實現

好久沒幹這塊東西了,近幾天需要做這個,所以重新學了一下,首先非常感謝孔浩老師,沒孔浩老師的視頻我也不會進入lucene的殿堂。
老師當時講的實時搜索還是NRTManager,現在已經都變了,這個類已經不存在了,在4.0之後消失的,到我現在使用的5.2.1都是下面的方法:

首先羅列會使用的特殊類(常用的不再贅述):

TrackingIndexWriter  追蹤writer,在api中有介紹,只有通過這個類進行更新ControlledRealTimeReopenThread才能獲得更新
ControlledRealTimeReopenThread  實時搜索其實叫做“近實時搜索”,就是當更新之後在很短時間內進行了更新然後讓人感覺不出來,這樣說來就需要一個守護線程去堅守這個過程,當更新的時候就去獲取更新然後通知查詢更新了,這樣“近實時搜索”就實現了,這個類就是這個守護線程。
我寫了個測試在下面,裏面不懂得可以查看api,也有部分註釋,希望對大家有幫助。


package com.xikoubuy.main;


import java.io.IOException;


import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.TrackingIndexWriter;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.ControlledRealTimeReopenThread;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ReferenceManager;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.SearcherFactory;
import org.apache.lucene.search.SearcherManager;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;


public class NRTTest {


private Directory directory;
private Analyzer analyzer;
////追蹤writer,這樣才能在更新之後通知搜索
private TrackingIndexWriter writer;
//是線程安全的.第二個參數是是否在所有緩存清空後讓search看到
private SearcherManager searcherManager;
private IndexSearcher searcher;

public static void main(String[] args) throws IOException {

new NRTTest();
}


public NRTTest() throws IOException {
directory = new RAMDirectory();
analyzer = new IKAnalyzer(true);
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
writer = new TrackingIndexWriter(indexWriter);
searcherManager = new SearcherManager(indexWriter, true, new SearcherFactory());
ControlledRealTimeReopenThread CRTReopenThead = new ControlledRealTimeReopenThread(writer, searcherManager, 5.0, 0.025);
//守護線程,又叫後臺線程,級別比較低,如果沒有主線程這個也會消失,這個線程作用就是定期更新讓searchManager管理的search能獲得更新
CRTReopenThead.setDaemon(true);
CRTReopenThead.setName("更新線程");
CRTReopenThead.start();
this.addDoc();
this.searchDoc();
}

public synchronized void addDoc(){
final int i = 0;
new Thread(){

public  void run() {
while(true){
try {
Thread.sleep(10000);
System.out.println("----加入文檔中");
Document doc = new Document();
doc.add(new Field("title", "標題" + i, TextField.TYPE_STORED));
doc.add(new Field("content", "我愛你中國" + i, TextField.TYPE_STORED));
writer.addDocument(doc);

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}.start();
}

public synchronized void searchDoc(){
new Thread(){
public void run() {
while(true){
try {
Thread.sleep(5000);
System.out.println("----檢索中");
searcher = searcherManager.acquire();
QueryParser parser = new QueryParser("content", analyzer);
Query query = parser.parse("中國");
ScoreDoc [] hits = searcher.search(query, 100).scoreDocs;
for(int i = 0; i < hits.length;i++){
Document doc = searcher.doc(hits[i].doc );
System.out.println(doc.get("title") + hits[i].doc);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
try {
searcherManager.release(searcher);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
searcher = null;
}
};
}.start();
}


}

發佈了36 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章