在lucene的搜索示例中,很多demo代码在做搜索的时候都是先新建一个IndexReader,之后再新建一个IndexSearcher,搜索完成之后,再将IndexReader关闭。
但在实际项目应用中,这样操作是不妥当的。
对于IndexReader来说,IndexReader.open()会产生很大开销。
对于IndexSearcher来说,创建IndexSearcher时,程序是把索引文件全部载入内存,你查询一次,就要载入一次。
所以,对于一个index下的IndexReader和IndexSearch应该是单例的
新建一个LuceneFactory类,来提供单例的IndexReader和IndexSearcher
public class LuceneFactory {
public static String path;
//IndexReader设置为单例
private static IndexReader busLineReader = null;
//IndexSearcher设置为单例
private static IndexSearcher busLineSearcher = null;
static {
Directory busLineDirectory = null;
try {
busLineDirectory = FSDirectory.open(Paths.get(Util.getConfigParam("lucene.busLine_index.path")));
} catch (IOException e) {
e.printStackTrace();
}
try {
busLineReader = DirectoryReader.open(busLineDirectory);
} catch (IOException e) {
e.printStackTrace();
}
}
public static synchronized IndexSearcher getBusLineSearcher() {
if (busLineReader != null) {
try {
IndexReader changeReader = DirectoryReader.openIfChanged((DirectoryReader) busLineReader);
if (changeReader != null) {
busLineReader.close();
busLineReader = changeReader;
}
} catch (IOException e) {
e.printStackTrace();
}
busLineSearcher = new IndexSearcher(busLineReader);
return busLineSearcher;
}else{
throw new NullPointerException("创建单例busLineReader失败");
}
}
}
需要说明的一点是:在上面的代码中调用了DirectoryReader.openIfChanged方法,目的是当index文件更新的时候,重新生成IndexReader,否则IndexReader不会更新,除非重启项目。