我正在更新使用Lucene索引的工具。作为此更新的一部分,我们将从Lucene 2.0.0迁移到3.0.2。在大多数情况下,这完全是直截了当的。但是,在一个例子中,我似乎无法找到直接的转换。
基本上我有一个简单的查询,我需要迭代所有命中。在Lucene 2中,这很简单,例如:
Hits hits = indexSearcher.search(query);
for(int i=0 ; i<hits.length() ; i++){
// Process hit
}
在Lucene 3中,IndexSearcher
的API发生了重大变化,虽然我可以将有效的内容捆绑在一起,但只能获取前X
个文档,并确保X
是足够大。
虽然点击次数(在我的情况下)通常在0到10之间,但是有一些异常情况,他们的数字可能会高得多。因此有一个固定的限制感觉不对。此外,将限制设置为非常高会导致OOME,这意味着立即分配所有X
可能命中的空间。由于此操作是 alot ,因此需要一些合理有效的方法。
修改
目前我有以下工作:
TopDocs hits = indexSearcher.search(query, MAX_HITS);
for (int i=0 ; i<hits.totalHits ; i++) {
// Process hit
}
除了
之外,这种方法很好 a)如果有更多点击次数MAX_HITS
怎么办?
和
b)如果MAX_HITS很大,那么我就会浪费内存,因为在执行搜索之前会分配每次点击的空间。
由于大部分时间只会有一些点击,我不介意跟进搜索以获得后续点击,但我似乎无法找到一种方法来做到这一点。
答案 0 :(得分:2)
IndexSearcher有一个方法docFreq(Term)
。调用它似乎没有性能损失,并且它的输出是一个合适的输入参数,用于获取的文档数。
E.g。
int freq = searcher.docFreq(new Term(FIELD, value));
TopDocs hits = indexSearcher.search(query, freq);
for (int i=0 ; i<hits.totalHits ; i++) {
// Process hit
}
这是有效的,因为我的查询基本上是TermQuery
。如果这是一个更复杂的查询,那么这将不合适。
答案 1 :(得分:2)
@Kris - 我也遇到过这个问题,这对我有用。试试这个:
TopDocs tp = ms.search(query, 1);
TopDocs hits = indexSearcher.search(query, tp.totalHits);
for (int i=0 ; i<hits.totalHits ; i++) {
// Process hit
}
根据Uwe在下面的链接中tp.totalHits“..仍会计算所有点击次数,但只返回1.”
查看java-user lucene apache邮件档案链接中的完整详细信息 - http://www.gossamer-threads.com/lists/lucene/java-user/95032
答案 2 :(得分:0)
为什么不使用Searcher.search(查询查询,int n)?您可以指定要返回的结果数,并且可以使用返回的TopDocs对象来迭代结果。
使用Hits处理长结果集是一个坏主意,因为在后台hits对象会运行更多搜索来填充它尚未拥有的结果。
TopDocs只包含ID和分数,所以即使是大n也不应该有内存问题。
答案 3 :(得分:0)
如何使用索引阅读器中的NumDocs作为最大结果数。
请注意索引中零文档的边缘情况,但是......
希望这有帮助,