Lucene.NET 不是删除文档吗?
Lucene.NET is not deleting docs?
我可能经历过无数次 S.O。关于这个问题的帖子,但我很茫然,无法弄清楚问题是什么。
我可以在索引中添加和更新文档,但我似乎无法成功删除它们。
我正在使用 Lucene.NET
v3.0.3
我读到一个建议是使用相同条件执行 查询 并确保我得到返回结果。好吧,我这样做了:
首先,我有一个方法可以将数据库中 returns 项标记为已删除
var deletedItems = VehicleController.GetDeleted(DateTime lastcheck);
目前在测试期间,这包括一个项目。然后我迭代:
// This method returns my writer
var indexWriter = LuceneController.GetWriter();
// And my searcher
var searcher = new IndexSearcher(indexWriter.GetReader());
// And iterate over my items (just one for testing)
foreach(var c in deletedItems) {
// Here I'm testing by doing a query
var query = new BooleanQuery();
query.Add(new TermQuery(new Term("key", c.Guid.ToString())), Occur.MUST);
// Let's see if it can find the record based on this
var docs = searcher.Search(query, 1);
var foundDoc = docs.FirstOrDefault();
// Yep, we have one... let's get the full doc to be sure
var actualDoc = searcher.Doc(foundDoc.Doc);
// If I inspect actualDoc, it's the right one... I want to delete it.
indexWriter.DeleteDocuments(query);
indexWriter.Commit();
}
为了更容易阅读,我试图把上面的逻辑全部打碎,但是我尝试了各种方法...
indexWriter.Optimize();
indexWriter.Flush(true, true, true);
如果我查看存储所有内容的实际文件夹,我可以看到 0_1.del
之类的文件名和弹出窗口之类的内容,这看起来很有希望。
然后我在某处阅读了有关合并策略的信息,但这不是 Flush
应该做的吗?
然后阅读以尝试将优化方法设置为最大 1,但仍然无效(即 indexWriter.Optimize(1)
)。
因此,使用相同的查询来获取有效,但删除无效。为什么?我还能检查什么?删除实际上是永久删除该项目还是以其他方式继续存在,直到我完全删除正在使用的目录?没看懂。
Lucene 中的索引段文件是不可变的,一旦写入就永远不会改变。因此,当记录删除时,删除的记录实际上并没有立即从索引文件中删除,只是将记录标记为已删除。一旦合并该索引段以生成新段,该记录最终将从索引中删除。即删除的记录不会在合并结果的新段中。
理论上,一旦 commit
被调用,删除应该从 reader 的视图中删除,因为您从作者那里得到 reader(即它是实时 reader) 这在此处记录:
Note that flushing just moves the internal buffered state in IndexWriter into the index, but these changes are not visible to IndexReader until either commit() or close() is called.
来源:https://lucene.apache.org/core/3_0_3/api/core/org/apache/lucene/index/IndexWriter.html
但您可能想在删除发生后尝试关闭 reader,然后从作者那里获取新的 reader,看看新的 reader 现在是否有记录从可见性中移除。
我可能经历过无数次 S.O。关于这个问题的帖子,但我很茫然,无法弄清楚问题是什么。
我可以在索引中添加和更新文档,但我似乎无法成功删除它们。
我正在使用 Lucene.NET
v3.0.3
我读到一个建议是使用相同条件执行 查询 并确保我得到返回结果。好吧,我这样做了:
首先,我有一个方法可以将数据库中 returns 项标记为已删除
var deletedItems = VehicleController.GetDeleted(DateTime lastcheck);
目前在测试期间,这包括一个项目。然后我迭代:
// This method returns my writer
var indexWriter = LuceneController.GetWriter();
// And my searcher
var searcher = new IndexSearcher(indexWriter.GetReader());
// And iterate over my items (just one for testing)
foreach(var c in deletedItems) {
// Here I'm testing by doing a query
var query = new BooleanQuery();
query.Add(new TermQuery(new Term("key", c.Guid.ToString())), Occur.MUST);
// Let's see if it can find the record based on this
var docs = searcher.Search(query, 1);
var foundDoc = docs.FirstOrDefault();
// Yep, we have one... let's get the full doc to be sure
var actualDoc = searcher.Doc(foundDoc.Doc);
// If I inspect actualDoc, it's the right one... I want to delete it.
indexWriter.DeleteDocuments(query);
indexWriter.Commit();
}
为了更容易阅读,我试图把上面的逻辑全部打碎,但是我尝试了各种方法...
indexWriter.Optimize();
indexWriter.Flush(true, true, true);
如果我查看存储所有内容的实际文件夹,我可以看到 0_1.del
之类的文件名和弹出窗口之类的内容,这看起来很有希望。
然后我在某处阅读了有关合并策略的信息,但这不是 Flush
应该做的吗?
然后阅读以尝试将优化方法设置为最大 1,但仍然无效(即 indexWriter.Optimize(1)
)。
因此,使用相同的查询来获取有效,但删除无效。为什么?我还能检查什么?删除实际上是永久删除该项目还是以其他方式继续存在,直到我完全删除正在使用的目录?没看懂。
Lucene 中的索引段文件是不可变的,一旦写入就永远不会改变。因此,当记录删除时,删除的记录实际上并没有立即从索引文件中删除,只是将记录标记为已删除。一旦合并该索引段以生成新段,该记录最终将从索引中删除。即删除的记录不会在合并结果的新段中。
理论上,一旦 commit
被调用,删除应该从 reader 的视图中删除,因为您从作者那里得到 reader(即它是实时 reader) 这在此处记录:
Note that flushing just moves the internal buffered state in IndexWriter into the index, but these changes are not visible to IndexReader until either commit() or close() is called.
来源:https://lucene.apache.org/core/3_0_3/api/core/org/apache/lucene/index/IndexWriter.html
但您可能想在删除发生后尝试关闭 reader,然后从作者那里获取新的 reader,看看新的 reader 现在是否有记录从可见性中移除。