gpt4 book ai didi

java - Lucene 不断添加文档,而使用 updateDocument

转载 作者:行者123 更新时间:2023-12-02 11:02:22 25 4
gpt4 key购买 nike

我的项目围绕 Lucene 6.6.0 展开。实际上,它涉及一个用 java 编写的桌面搜索引擎,其中搜索部分与索引部分位于单独的应用程序中。有时我必须向索引添加新字段以满足客户需求,而不必重新索引(即解析文件+索引)所有内容。

因此,当应用程序启动时,我使用 IndexWriter,打开与其关联的 IndexReader :

IndexReader reader = DirectoryReader.open(writer, true, false);

然后对于索引中已存在的每个文档:

StoredField fieldVersion = new StoredField(
FIELDNAME_VERSION,
fixedValue // The value is the same for all the documents but may change (for all documents) when upgrading the version.
);

for (int i = 0; i < idMax; i++) {

Document currentDoc = reader.document(i);
// Checks if the field exists in the index
if (
// Field does not exist yet
currentDoc.get(FIELDNAME_VERSION) == null ||
// Field value is different from what it should be
!currentDoc.get(FIELDNAME_VERSION).contentEquals(fixedValue))
{
// THe field does not exist so we add it to the doc and beforehand removes the field from the currentDoc (also tried without removing first with the same result)
currentDoc.removeField(FIELDNAME_VERSION);
currentDoc.add(fieldVersion);
// Updates the document in the index
writer.updateDocuments(
new Term(FIELDNAME_PATH, currentDoc.get(FIELDNAME_PATH),
currentDoc);

// also tried with
writer.deleteDocuments(new Term(FIELDNAME_PATH,
currentDoc.get(FIELDNAME_PATH)));
writer.addDocument(currentDoc);
}
}
// When all documents have been checked, write the index
writer.commit();

当我第一次运行此字段时,该字段会按预期添加到所有没有该字段的文档中。问题是,当fixedValue更改时,新文档会添加到索引中,而我希望currentDoc更新其fieldVersion,而不是创建另一个文档,其值与除fieldVersion之外的所有字段的原始值相同。

IndexWriter 处于追加模式(也尝试使用追加或创建)。如果我首先索引单个文件,我会在索引中得到 1 个文档,然后在索引更新后,我会得到 2 个文档,然后是 4 个,然后是 8 个,然后是 16 个,...始终引用同一个文件(仅 fieldVersion有不同的内容)。

This other SO question没有帮助我。

当我要求 Lucene 更新现有文档时,为什么 Lucene 添加新文档?应该采取什么措施来解决此问题(即用相同的文档替换现有文档,只需使用不同的 fieldVersion 内容?

编辑 1:

调用此方法后,似乎缺少一个字段。该字段通过以下方式初始化:

 new TextField(FIELDNAME_UNSTORED,
"",
Field.Store.NO);

所以它没有被存储。

与FIELDNAME_PATH关联的字段初始化为

StringField pathField = new StringField(FIELDNAME_PATH,
"",
Field.Store.YES);

编辑2:

我实际上没有得到的是,如果我只执行 deleteDocuments(new Term(...)) 那么所有文档都会从索引中删除(如预期),但是如果我添加删除 add(currentDoc) 之后,我得到的文档数量是原来的两倍。就好像该文档在其原始版本中添加了一次,在其更新版本中添加了第二次。

解决方案:

正如 @femtoRgon 所指出的,路径字段在索引过程中没有被标记化。但后来它被自动标记化了。因此,解决方案是在索引期间重新创建路径字段(以及其他字段),使用临时 Document 来存储字段,然后使用此 updateDocument()临时文档

非常感谢任何帮助!

最佳答案

lucene中的更新总是添加一个新文档,它只是先删除与给定术语匹配的所有文档,并且无论是否找到要删除的文档,它都会愉快地添加新文档。因此,无论出于何种原因,您都无法在该术语上找到匹配项。您尚未展示如何对 FIELDNAME_PATH 进行索引,但对于此处的模式,应该对其进行索引而不是标记化(即使用 StringField)。

您只需运行 TermQuery 即可测试传递给更新的术语是否有效。如果您从 TermQuery 得到 0 个结果,则 IndexWriter.UpdateDocuments 也不会找到要删除的文档。

<小时/>

就缺少未存储字段而言,是的,您在此处使用的模式无法很好地处理未存储字段。未存储的字段不包含在从 IndexReader.document 返回的文档中(这就是存储字段的目的,以便可以从索引中检索它)。因此,由于结果中缺少该值,因此您传递到更新的文档中仍然会缺少该值,除非您以其他方式重新创建该值。要么从您正在使用的任何源 Material 重建文档,要么确保存储您想要在更新中保留的任何内容。

关于java - Lucene 不断添加文档,而使用 updateDocument,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51226749/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com