我正在使用Lucene.NET(v2.0)在Visual Basic 9(VS2008)中开发桌面搜索引擎。
我使用以下代码初始化IndexWriter
Private writer As IndexWriter
writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), False)
writer.SetUseCompoundFile(True)
如果我选择同一个文档文件夹(包含要编制索引的文件)两次,则会在索引中为该文档文件夹中的每个文件创建两个不同的条目。
我希望IndexWriter丢弃索引中已存在的所有文件。
我该怎么做才能确保这一点?
答案 0 :(得分:19)
正如Steve所提到的,您需要使用IndexReader的实例并调用其DeleteDocuments方法。 DeleteDocuments接受Term对象的实例或Lucene的文档内部id(通常不建议尽可能使用内部id,并且会随着Lucene合并段而改变)。
最好的方法是使用您存储在特定于您的应用程序的索引中的唯一标识符。例如,在医生办公室的患者索引中,如果您有一个名为“patient_id”的字段,您可以创建一个术语并将其作为参数传递给DeleteDocuments。请参阅以下示例(抱歉,C#):
int patientID = 12;
IndexReader indexReader = IndexReader.Open( indexDirectory );
indexReader.DeleteDocuments( new Term( "patient_id", patientID ) );
然后,您可以使用IndexWriter实例再次添加患者记录。我从这篇文章http://www.codeproject.com/KB/library/IntroducingLucene.aspx中学到了很多东西。
希望这有帮助。
答案 1 :(得分:11)
有许多关于使用id字段删除的过时示例。下面的代码适用于Lucene.NET 2.4。
如果您已经在使用IndexWriter或访问IndexSearcher.Reader,则无需打开IndexReader。您可以使用IndexWriter.DeleteDocuments(Term),但棘手的部分是确保您首先正确存储了您的id字段。在存储文档时,请确保使用Field.Index.NOT_ANALYZED作为id字段的索引设置。这会对字段编制索引而不对其进行标记,这非常重要,并且当使用这种方式时,其他任何Field.Index值都不会起作用:
IndexWriter writer = new IndexWriter("\MyIndexFolder", new StandardAnalyzer());
var doc = new Document();
var idField = new Field("id", "MyItemId", Field.Store.YES, Field.Index.NOT_ANALYZED);
doc.Add(idField);
writer.AddDocument(doc);
writer.Commit();
现在,您可以使用同一个编写器轻松删除或更新文档:
Term idTerm = new Term("id", "MyItemId");
writer.DeleteDocuments(idTerm);
writer.Commit();
答案 2 :(得分:5)
如果您要删除索引中的所有内容并重新填充,可以使用此声明
writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), True)
IndexWriter constructor的最后一个参数确定是创建新索引,还是打开现有索引以添加新文档。
答案 3 :(得分:4)
要更新lucene索引,您需要删除旧条目并写入新条目。因此,您需要使用IndexReader查找当前项目,使用writer删除它,然后添加新项目。对于我认为你正在尝试做的多个条目也是如此。只需找到所有条目,将它们全部删除然后写入新条目。
答案 4 :(得分:4)
下面列出了一些选项,可根据要求使用。
见下面的代码快照。 [C#中的源代码,请将其转换为vb.net]
Lucene.Net.Documents.Document doc = ConvertToLuceneDocument(id, data);
Lucene.Net.Store.Directory dir = Lucene.Net.Store.FSDirectory.Open(new DirectoryInfo(UpdateConfiguration.IndexTextFiles));
Lucene.Net.Analysis.Analyzer analyzer = new Lucene.Net.Analysis.Standard.StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29);
Lucene.Net.Index.IndexWriter indexWriter = new Lucene.Net.Index.IndexWriter(dir, analyzer, false, Lucene.Net.Index.IndexWriter.MaxFieldLength.UNLIMITED);
Lucene.Net.Index.Term idTerm = new Lucene.Net.Index.Term("id", id);
foreach (FileInfo file in new DirectoryInfo(UpdateConfiguration.UpdatePath).EnumerateFiles())
{
Scenario 1: Single step update.
indexWriter.UpdateDocument(idTerm, doc, analyzer);
Scenario 2: Delete a document and then Update the document
indexWriter.DeleteDocuments(idTerm);
indexWriter.AddDocument(doc);
Scenario 3: Take necessary steps if a document does not exist.
Lucene.Net.Index.IndexReader iReader = Lucene.Net.Index.IndexReader.Open(indexWriter.GetDirectory(), true);
Lucene.Net.Search.IndexSearcher iSearcher = new Lucene.Net.Search.IndexSearcher(iReader);
int docCount = iSearcher.DocFreq(idTerm);
iSearcher.Close();
iReader.Close();
if (docCount == 0)
{
//TODO: Take necessary steps
//Possible Step 1: add document
//indexWriter.AddDocument(doc);
//Possible Step 2: raise the error for the unknown document
}
}
indexWriter.Optimize();
indexWriter.Close();
答案 5 :(得分:3)
除非您只修改少量文档(例如,少于总数的10%),否则几乎肯定会更快(您的里程可能因存储/索引字段等而异)从头开始重新索引。
那就是说,我总是会索引到一个临时目录,然后在完成后将新的目录移动到位。这样,在索引构建时几乎没有停机时间,如果出现问题,您仍然可以获得良好的索引。
答案 6 :(得分:2)
当然,一个选项是删除文档,然后添加文档的更新版本。
或者,您也可以使用IndexWriter类的UpdateDocument()方法:
writer.UpdateDocument(new Term("patient_id", document.Get("patient_id")), document);
这当然要求您有一种机制,通过该机制可以找到要更新的文档(在此示例中为“patient_id”)。
我有blogged more details with a more complete source code example。