【问题标题】:Lucene can't find documents after updateLucene 更新后找不到文档
【发布时间】:2014-09-17 14:00:36
【问题描述】:

似乎每当我更新索引中的现有文档(删除/添加的行为相同)时,都无法使用 TermQuery 找到它。这是一个简短的 sn-p:

iw = new IndexWriter(目录,配置);

Document doc = new Document();
doc.add(new StringField("string", "a", Store.YES));
doc.add(new IntField("int", 1, Store.YES));

iw.addDocument(doc);

Query query = new TermQuery(new Term("string","a"));

Document[] hits = search(query);
doc = hits[0];
print(doc);

doc.removeField("int");
doc.add(new IntField("int", 2, Store.YES));

iw.updateDocument(new Term("string","a"), doc);

hits = search(query);
System.out.println(hits.length);
System.out.println("_________________");

for(Document hit : search(new MatchAllDocsQuery())){
    print(hit);
}

这会产生以下控制台输出:

stored,indexed,tokenized,omitNorms,indexOptions=DOCS_ONLY<string:a>
stored<int:1>
________________
0
_________________
stored,indexed,tokenized,omitNorms,indexOptions=DOCS_ONLY<string:a>
stored<int:2>
________________

似乎更新后,索引中的文档(而不是新文档)被 MatchAllDocsQuery 返回,但无法被 TermQuery 找到。

完整的示例代码可在http://pastebin.com/sP2Vav9v获得

此外,只有当 StringField 值包含特殊字符(例如 file:/F:/)时,才会发生这种情况(第二次搜索不起作用)。

【问题讨论】:

  • 你不缺iw.commit() 吗?
  • 不会改变任何东西。已经试过了。此外,搜索每次都会从作者那里打开一个新的阅读器: DirectoryReader reader = DirectoryReader.open(iw, true);
  • 我似乎遇到了类似的问题。这是哪个版本的 Lucene?
  • 试用了 4_6 和 4_10 之间的多个版本。

标签: java lucene


【解决方案1】:

您在 pastebin 中引用的代码没有找到任何内容,因为您的 StringField 只是一个停用词 (a)。将 a 替换为非停用词(例如 ax)会使两个搜索都返回 1 个文档。

如果您要构造带有空停用词集 (CharArraySet.EMPTY_SET) 的 StandardAnalyzer,但仍将 a 用于 StringField,您也将获得正确的结果。不过,这不适用于file:/F:/

但是,最好的解决方案是在这种情况下将StandardAnalyzer 替换为KeywordAnalyzer

【讨论】:

  • 我认为 StringField 没有被分析?另外,为什么更新会有这种效果,而插入新文档却没有?
  • StringField 没有被分析,这是正确的。但仍应用停用词过滤器 - 请参阅 StandardAnalyzer Javadoc。 Lucene in Action 书(第 120-121 页)说:“StandardAnalyzer 还包括停用词删除”。关于更新/插入问题——我不完全确定。如果找到任何结果,我会尝试调试并发布结果。
【解决方案2】:

我可以通过在所有索引操作之后重新创建我的工作目录来摆脱这个: 例如,为此索引操作创建一个名为“path_dir”的新目录。如果您已更新,则调用以下操作并再次执行您之前的所有工作。

StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_46);
FSDirectory dir;
try {
    // delete indexing files :
    dir = FSDirectory.open(new File(path_dir));
    IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_46, analyzer);
    IndexWriter writer = new IndexWriter(dir, config);
    writer.deleteAll();
    writer.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

但是,请注意,如果您正在处理大数据,这种方式会非常慢。

【讨论】:

  • 这究竟是如何“修复”的?删除索引绝对是荒谬的!如果您需要更新 10 000 000 条记录 5 次并且每次都必须删除索引会怎样?!这是不可接受的。
  • 我已经在回答的末尾评论了大数据。我可以通过这种方式使我的代码正常工作。因为我不处理大数据,所以这对我来说不是问题。如果 michael 也有小数据,它可能会工作。
猜你喜欢
  • 2020-01-28
  • 2018-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-20
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多