有人可以帮我解决在Lucene中使用抽象收集器类的自定义实现的方法吗?
我已经实现了两种使用一些测试文本查询索引的方法:
1.总命中数是2。两个文件名都相同,因此结果大小为1,因为我将它们保存在一个集合中。
TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
LOG.info("Total hits " + topDocs.totalHits);
ScoreDoc[] scoreDosArray = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDosArray) {
Document doc = searcher.doc(scoreDoc.doc);
String fileName = doc.get(FILENAME_FIELD);
results.add(fileName);
}
2.CountCollect是eq to 2.我从Collector的collect方法中获取文件名的两个文件都是唯一的,因此最终结果大小也是eq到2. CountNextReader变量在逻辑结尾处是eq to 10。
private Set<String> doStreamingSearch(final IndexSearcher searcher, Query query) throws IOException {
final Set<String> results = new HashSet<String>();
Collector collector = new Collector() {
private int base;
private Scorer scorer;
private int countCollect;
private int countNextReader;
@Override
public void collect(int doc) throws IOException {
Document document = searcher.doc(doc);
String filename = document.get(FILENAME_FIELD);
results.add(filename);
countCollect++;
}
@Override
public boolean acceptsDocsOutOfOrder() {
return true;
}
@Override
public void setScorer(Scorer scorer) throws IOException {
this.scorer = scorer;
}
@Override
public void setNextReader(AtomicReaderContext ctx) throws IOException {
this.base = ctx.docBase;
countNextReader++;
}
@Override
public String toString() {
LOG.info("CountCollect: " + countCollect);
LOG.info("CountNextReader: " + countNextReader);
return null;
}
};
searcher.search(query, collector);
collector.toString();
return results;
}
我不明白为什么在collect方法中我会得到与之前实现相比不同的文档和不同的文件名?我期待相同的结果,或者?
答案 0 :(得分:11)
Collector#collect
方法是搜索请求的热点。它会调用与查询匹配的每个文档,而不仅仅是您获取的文档。实际上,您通常只返回顶级文档,这些文档实际上是您向用户显示的文档。
我建议不要做以下事情:
TopDocs topDocs = searcher.search(query, Integer.MAX_VALUE);
这将迫使lucene返回太多文件。
无论如何,如果您只有两个匹配的文档(或者您要求所有匹配的文档),您获取的文档数量和对collect方法的调用次数应该相同。
setNextReader
方法完全不同,你不应该太在意。如果您想了解更多有关AtomicReader等信息,请查看this article。为了简短起见,Lucene将数据存储为段,这些段是迷你可搜索的反向索引。每个查询按顺序在每个段上执行。每次搜索切换到下一个段时,都会调用setNextReader
方法,以允许在Collector
中的段级别执行操作。例如,内部lucene文档ID仅在段内是唯一的,因此您需要向其添加docBase
以使其在整个索引中唯一。这就是为什么您需要在细分变化时将其存储并将其考虑在内。您的countNextReader
变量只包含针对您的查询分析的细分数量,它与您的文档没有任何关系。
更深入地了解您的Collector
代码,我还注意到您在按ID检索文档时没有考虑docBase
。这应该解决它:
Document document = searcher.doc(doc + docBase);
请记住,在Collector
中加载存储的字段并不是一件明智的事情。它会让您的搜索速度变慢,因为存储的字段是从磁盘加载的。您通常仅为要返回的文档子集加载存储的字段。在Collector
内,您通常会加载对有效负载或类似内容等文档进行评分所需的信息,通常也会使用lucene字段缓存。