使用 Field.NoStore 更新 Lucene 文档

问题描述 投票:0回答:2

我使用的是Lucene.Net 3.0.3.0。

我有一个索引,其中包含具有多个字段和一些未存储的文档。当客户端有与此文档相关的更新时,我想更新相应文档的 ClientName 字段,但我遇到的问题是,当我尝试获取该客户端的所有文档时,更新该字段并放入文档回到索引中,未存储的字段将丢失。

所以像这样的文档:

DocId : 10
ClientId : 125
ClientName (Not stored) : Google
DocTitle (Not stored): Some title
DocContent (Not stored): content of my document

当客户端名称发生更新时,我必须更新字段 clientName,因此我在索引上搜索以查找 clientId 为 125 的所有文档,然后更新 clientname 字段并将文档删除/插入回指数。 但字段

DocTitle
DocContent
在此过程中丢失了。

如何更新

ClientName
字段而不丢失其他非存储字段?

编辑:根据建议,这是一段代码,用于迭代搜索结果以更新文档上的字段

for (int i = 0; i < collector.Docs.Count; i++)
{
    // retrieve the current document from the search result
    var oldDocument = searcher.Doc(collector.Docs[i]);
    var reviewId = oldDocument.Get(FIELD_ID);
    var updateTerm = new Term(FIELD_ID, reviewId);

    oldDocument.RemoveFields(FIELD_CLIENT_NAME);
    oldDocument.Add(new Field(FIELD_CLIENT_NAME, newClientName, Field.Store.NO, Field.Index.NOT_ANALYZED));

    //writer is an instance of Lucene.Net.Index.IndexWriter
    writer.UpdateDocument(updateTerm, oldDocument);
}

从那里开始,文档将正确保存在索引中,但未存储的字段 (

Field.Store.NO
) 会丢失,除了我刚刚更新的
FIELD_CLIENT_NAME

c# lucene lucene.net
2个回答
0
投票

不确定幕后发生了什么,但可以肯定的是,您正在尝试的不是在 Lucene 中更新文档的方法。

查看

removeField
org.apache.lucene.document.Document
方法的定义。

请注意,removeField(s) 方法(如 add 方法)仅在将文档添加到索引之前才有意义。 这些方法不能 用于更改现有索引的内容! 为了实现此目的,必须从索引中删除文档,并且必须添加该文档的新更改版本。

如您所知,更新方法将首先删除与所提供术语匹配的文档,然后添加新文档。

根据我们项目的实践,我能想到的一种可能的方法如下。

假设所有文档都从数据库中索引。所以一旦数据库记录更新,你也必须更新相应的 Lucene 文档。

伪代码可能是这样的

  indexWriter.updateDocument(
    //databaseRecordId is normally the primary key of updated record
    new Term("docId", databaseRecordPId) 
    indexedDocument // find the updated database record and index it
  )

如果您的 Lucene 文档不是“来自”数据库记录,请忘记我所说的。

无论如何,希望对你有帮助。


0
投票

我也证实了这种行为。 任何未标记为“已存储”的索引字段都将从索引中丢失。

我的工作是确定如何按需检索非存储字段,以便在更新操作期间将它们添加回文档中,或者如果该字段非常小,我只需继续将其最初索引为“存储”,以便文档更新时不需要重新添加。

这真是一个耻辱,因为我很乐意接受一些索引碎片,而不必存储数据。 我能够嵌入索引而无需存储所有字段并启用嵌入式客户端搜索,从而节省了大量空间。

© www.soinside.com 2019 - 2024. All rights reserved.