有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

我的问题是:测试集合(即时间集合)中的文档有自己的文档ID——但是,这些文档可能有间隙(例如:时间集合包含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必须是>;=0和<;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成为一个正常的领域,但也许我完全走错了方向?任何帮助都将不胜感激

非常感谢! 简


共 (1) 个答案

  1. # 1 楼答案

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

    数字字段(如IntField)不作为纯文本编制索引,而是编码成一种形式,使搜索数字范围变得高效。要搜索它们,应该使用^{},例如:

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

    然而,如果这是一个典型的id字段,我不会使用IntField。大多数像这样的时间标识符是由数字组成的,这是为了方便,而不是因为它们代表有意义的数字。一般来说,如果用数字范围搜索该字段没有意义,那么最好使用StringField