使用Lucene,我正在对包含文档,查询和相关文件(qrels)的相当经典的Testcollections进行一些评估。 qrels告诉我们lucene应该返回哪些文件与特定查询相关,因此可以测量lucenes搜索质量(使用一些参数,但现在这并不重要)。
我的问题是:测试集合中的文档(即TIME集合)有自己的文档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必须> = 0且< maxDoc = 423(得到docID = 520)”。
使lucene正确访问Document 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,但也许我在这里完全走错了路?我们非常感谢任何帮助。
提前多多感谢! 扬
答案 0 :(得分:0)
关于Lucene的内部DocID(即您在ScoreDoc.doc
中看到的),您不应将其用作外部ID。它们可以在没有警告的情况下进行更改(尤其是在您更新文档时)。
数字字段(例如IntField)不会作为纯文本编制索引,而是编码为使数字范围搜索高效的表单。要搜索它们,您应该使用NumericRangeQuery
,例如:
Query query = NumericRangeQuery.newIntRange(Constants.INDEX_ID_FIELD, docIdx, docIdx, true, true);
但是,如果这是一个典型的id字段,我就不会使用IntField
。大多数时候这样的标识符是为了方便而由数字组成,而不是因为它们代表有意义的数字。通常情况下,如果使用数字范围搜索该字段没有意义,则最好使用StringField
代替。