11

我正在使用 Lucene.NET (v2.0) 在 Visual Basic 9 (VS2008) 中开发桌面搜索引擎。

我使用以下代码来初始化 IndexWriter

Private writer As IndexWriter

writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), False)

writer.SetUseCompoundFile(True)

如果我两次选择同一个文件夹(包含要编制索引的文件),则会在索引中为该文件夹中的每个文件创建两个不同的条目。

我希望 IndexWriter 丢弃索引中已经存在的任何文件。

我应该怎么做才能确保这一点?

4

7 回答 7

20

正如史蒂夫所提到的,您需要使用 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中学到了很多东西。

希望这可以帮助。

于 2009-01-28T15:41:17.553 回答
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();
于 2010-02-02T22:58:49.573 回答
6

要更新 lucene 索引,您需要删除旧条目并写入新条目。因此,您需要使用 IndexReader 查找当前项目,使用 writer 删除它,然后添加新项目。对于我认为您正在尝试做的多个条目也是如此。只需找到所有条目,将它们全部删除,然后写入新条目。

于 2009-01-24T16:27:15.380 回答
6

如果要删除索引中的所有内容并重新填充,可以使用此语句

writer = New IndexWriter(indexDirectory, New StandardAnalyzer(), True)

IndexWriter 构造函数的最后一个参数确定是否创建新索引,或者是否打开现有索引以添加新文档。

于 2009-01-24T16:30:20.630 回答
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();
于 2011-10-25T07:28:53.967 回答
3

除非您只修改少量文档(例如,少于总数的 10%),否则从头开始重新索引几乎肯定会更快(您的里程可能会因存储/索引字段等而异)。

也就是说,我总是会索引到一个临时目录,然后在完成后将新目录移动到位。这样,在构建索引时几乎没有停机时间,如果出现问题,您仍然有一个好的索引。

于 2009-02-10T13:57:20.687 回答
2

一种选择当然是删除文档,然后添加文档的更新版本。

或者,您也可以使用 IndexWriter 类的 UpdateDocument() 方法:

writer.UpdateDocument(new Term("patient_id", document.Get("patient_id")), document);

这当然需要您有一种机制,您可以通过该机制找到要更新的文档(本示例中的“患者 ID”)。

我已经用更完整的源代码示例在博客上发布了更多详细信息

于 2010-07-31T05:26:34.807 回答