我正在开发一个将在后台线程上运行的“索引服务”(作为WPF应用程序的一部分),并使用FileSystemWatcher来监视某些文件。当文件内容改变时,我想提取一些信息并更新Lucene索引。有时,用户可能希望对索引执行搜索。
每次用户执行搜索时,我是否应该创建索引阅读器?每次索引更新时都有作家?或者我的索引服务类(单例)是否可以使用单例读取器和编写器实例(加上单独的FSDirectory,它们都具有依赖性)?
如果我要使用单例实例,我是否需要担心关闭/处理它们?如果是,我的索引服务应该实现IDisposable
,并在Dispose()
中进行清理吗?
答案 0 :(得分:1)
Lucene的InderWriter
和IndexReader
实例都是线程安全的:您不应该将它们重新用作单例。初始化一个新实例非常昂贵(当为写入和搜索做出类似的设计选择时,显着改善,后者接近60%)。
对于IndexWriter
,只需保留通过IndexingService
公开的私有实例。对于IndexReader
,您需要一种可以处理索引更改的不同方法。基于来源,你可以做到,
public class IndexingService
...
public IndexReader GetReader()
{
var reopenedReader = this.reader.Reopen(openReadOnly: true);
if (reopenedReader != this.reader)
{
this.reader.Dispose();
return this.reader = reopenedReader;
}
return this.reader;
}
对this.reader.Reopen
的调用将首先检查读者是否是最新的(如果打开后没有发生任何变化),如果是,则它将自行返回。如果有更改,则阅读器将仅加载已更改的段,这通常比加载所有段更快。如果您希望多线程访问,还需要同步对阅读器的访问。
最后一件事:在应用程序关闭的情况下,你肯定需要处理资源,编写器和阅读器(使用Dispose()
方法)。如果不这样做可能会破坏索引。
答案 1 :(得分:0)
每次创建一个编写器并不是最佳选择,因此您最好等待一段时间并编写所有更改。您可以在用户执行搜索时推送更改,这实际上取决于您的索引编写的复杂程度。
当您将更改提交到索引时,您需要创建一个新的索引阅读器,否则它将不会获取更改。所以我想将索引阅读器重新编入你的索引例程。但是,除非您更新索引,否则不要重新创建阅读器,因为这会降低您的应用程序速度。