Lucene 外部文档 Id 偏离内部索引 docId

Lucene external document Id deviating from internal index docId

我正在使用 Lucene 对包含文档、查询和相关文件 (qrels) 的相当经典的 Testcollection 进行一些评估。 qrels 告诉我们 lucene 应该返回哪些与特定查询相关的文档,因此可以衡量 lucenes 搜索质量(使用一些参数,但现在这并不重要)。

我的问题是:测试集合(即 TIME 集合)中的文档有自己的文档 ID - 但是,这些文档 ID 可能存在间隙(例如:TIME 集合包含 423 个文档,但以文档 ID 17 开头,以 ID 563 结尾)。文档 ID 被索引并存储为 IntField。

document.add(new IntField(Constants.INDEX_ID_FIELD, testDocument.getId(),Field.Store.YES));

但是,我可以(甚至不应该)使用 IndexReader.getTermVectors() 方法通过外部 ID 访问文档,因为 Lucene 在该方法中使用的内部 docId 与外部 ID 不匹配(因为间隙)。我收到一条错误消息 "docID must be >= 0 and < maxDoc=423 (got docID=520)".

使 lucene 正确访问文档 520 以通过内部 docId 调用文档的 getTermVectors 方法的首选方法是什么? 我试图通过这种方式获取正确的文档:

IndexSearcher searcher = myTestRunner.indexSearcher;
TermQuery query = new TermQuery(new Term(Constants.INDEX_ID_FIELD, String.valueOf(docIdx)));
TopDocs topdocs = searcher.search(query, 1);
ScoreDoc[] treffer = topdocs.scoreDocs;
int docId = treffer[0].doc;
Terms vector = myTestRunner.indexReader.getTermVector(docId, "content");
// ... some more code follows

但是,似乎找不到文档(但它在索引中 - 使用 Luke 检查)。我总是得到:

2015-03-19 12:23:25 ERROR ControlView:1002 - 0 java.lang.ArrayIndexOutOfBoundsException: 0
at de.janjan.irtool.querygenerator.QueryGenerator.getFrequencies(QueryGenerator.java:335)

我的下一个想法是让 IntField 成为一个普通的 Field,但也许我完全走错了路?非常感谢任何帮助。

非常感谢! 一月

关于 Lucene 的内部 DocID(即您在 ScoreDoc.doc 中看到的那个),您不应该将其用作外部 ID。它们可以在没有警告的情况下更改(尤其是当您更新文档时)。

数字字段(例如 IntField)未作为纯文本编制索引,而是编码为一种形式,可以有效地搜索数字范围。要搜索它们,您应该使用 NumericRangeQuery,例如:

Query query = NumericRangeQuery.newIntRange(Constants.INDEX_ID_FIELD, docIdx, docIdx, true, true);

但是,如果这是典型的 ID 字段,我不会使用 IntField。大多数时候像这样的标识符由数字组成是为了方便,而不是因为它们代表有意义的数字。通常,如果使用数字范围搜索该字段没有意义,最好使用 StringField 代替。