【问题标题】:Lucene updateDocument not deleting documentsLucene updateDocument 不删除文档
【发布时间】:2012-05-11 13:34:31
【问题描述】:

这似乎是一个常见的问题,除了我之前没有遇到过这个问题并且通常的修复不起作用。这可能是愚蠢的,但我找不到它。

我想索引一个 yammer 站点,因为 yammer api 对我的目的来说不够快,问题是当我尝试使用 updateDocument 功能更新我的索引时,旧的并没有被删除。但我有一个未分析的存储唯一键。

以下是相关代码:

Document newdoc = new Document();
newdoc.add(new Field(YammerMessageFields.URL, resultUrl, Field.Store.YES, Field.Index.NOT_ANALYZED));
newdoc.add(new Field(YammerMessageFields.THREAD_ID, threadID.toString(), Field.Store.YES, Field.Index.NOT_ANALYZED));
newdoc.add(new Field(YammerMessageFields.AUTHOR, senderName, Field.Store.YES, Field.Index.ANALYZED));
newdoc.add(new Field(YammerMessageFields.CONTENTS, resultText, Field.Store.YES, Field.Index.ANALYZED));
Term key = new Term(YammerMessageFields.THREAD_ID, newdoc.getFieldable(YammerMessageFields.THREAD_ID).toString());
logger.debug("updating document with key: " + key);
try {
    IndexWriter writer = getIndexWriter();
    writer.updateDocument(key, newdoc);
    writer.close();
} catch (IOException e) {
}

我在日志中看到的是:

2012-05-11 12:02:29,816 DEBUG [http-8088-2] LuceneIndex - https://www.yammer.com/api/v1/messages/?newer_than=0
2012-05-11 12:02:38,594 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173285202>
2012-05-11 12:02:45,167 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173033239>
2012-05-11 12:02:51,686 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173014568>
2012-05-11 12:02:51,871 DEBUG [http-8088-2] LuceneIndex - new items:3

2012-05-11 12:03:27,393 DEBUG [http-8088-2] YammerResource - return all documents
2012-05-11 12:03:27,405 DEBUG [http-8088-2] YammerResource - nr docs:3
2012-05-11 12:03:27,405 DEBUG [http-8088-2] YammerResource - nr dels:0

...
next update
...

2012-05-11 12:03:35,802 DEBUG [http-8088-2] LuceneIndex - https://www.yammer.com/api/v1/messages/?newer_than=0
2012-05-11 12:03:43,933 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173322760>
2012-05-11 12:03:50,467 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173285202>
2012-05-11 12:03:56,982 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173056406>
2012-05-11 12:04:03,533 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173033239>
2012-05-11 12:04:10,097 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173030769>
2012-05-11 12:04:16,629 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173014568>
2012-05-11 12:04:23,169 DEBUG [http-8088-2] LuceneIndex - updating document with key: threadid:stored,indexed<threadid:173003570>
2012-05-11 12:04:23,341 DEBUG [http-8088-2] LuceneIndex - new items:7

2012-05-11 12:05:09,694 DEBUG [http-8088-1] YammerResource - return all documents
2012-05-11 12:05:09,696 DEBUG [http-8088-1] YammerResource - nr docs:10
2012-05-11 12:05:09,696 DEBUG [http-8088-1] YammerResource - nr dels:0

所以密钥会再次出现(和 4 个新的),但是当这完成后,我的商店中有 10 个文档而不是 7 个(和 3 个已删除的文档)。

编辑:这是我找到这些项目的方式,但我实际上展示了它们并与 Luke 一起检查了它。

IndexReader r = IndexReader.open(searchIndex.getIndex());
                List<Document> docList = new ArrayList<Document>();
                List<Document> delList = new ArrayList<Document>();

                int num = r.numDocs();
                num += r.numDeletedDocs();
                for ( int i = 0; i < num && i < max; i++)
                {
                    if ( ! r.isDeleted( i))
                        docList.add(r.document(i));
                    else
                        delList.add(r.document(i));

                }
                r.close();
                logger.debug("nr docs:" + docList.size());
                logger.debug("nr dels:" + delList.size());

【问题讨论】:

  • 什么 API 调用用于查找文档计数?
  • 可能是。如果调用maxDoc,已知不考虑已删除的文档。当然,我说的是 Lucene API 调用。上面没有任何东西。

标签: java lucene yammer


【解决方案1】:

如果不运行一些测试代码,我不确定,但这对我来说是错误的:

Term key = new Term(YammerMessageFields.THREAD_ID, 
   newdoc.getFieldable(YammerMessageFields.THREAD_ID).toString());

你确定它不应该是:

Term key = new Term(YammerMessageFields.THREAD_ID, 
   newdoc.getFieldable(YammerMessageFields.THREAD_ID).stringValue());

然后您继续使用该密钥来尝试更新任何匹配的现有文档。如果密钥错误,那么文档更新可能会静默失败。我怀疑Term 上的toString() 实际上只会给你一个对象引用,这意味着更新永远不会起作用。

调用toString() 来进行日志记录或调试以外的任何事情(即任何包含逻辑的事情)通常都是错误的。

【讨论】:

  • .stringValue() 解决了这个问题。谢谢,奇怪的是这在另一个版本中有效......
  • 不,这并不奇怪。程序员频繁更改toString()方法的实现;这就是为什么您永远不应该依赖它们返回特定值的原因。
  • 顺便说一句更新没有失败,文件实际上是添加的,只是删除失败了。
  • 更新实际上是原子删除/添加 - 我不认为有办法在 Lucene 中“更新”文档。见lucene.apache.org/core/old_versioned_docs/versions/3_4_0/api/…, org.apache.lucene.document.Document)。如果删除无法匹配任何文档,则其中没有任何内容表明添加部分被中止。所以——因为没有匹配的文档替换“更新”失败。
  • @Jon 还有StringBuilder.toStringStringWriter.toString——还有很多其他的toString API。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
相关资源
最近更新 更多