Lucene 3迭代所有命中

时间:2010-07-21 14:23:23

标签: java lucene

我正在更新使用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很大,那么我就会浪费内存,因为在执行搜索之前会分配每次点击的空间。

由于大部分时间只会有一些点击,我不介意跟进搜索以获得后续点击,但我似乎无法找到一种方法来做到这一点。

4 个答案:

答案 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作为最大结果数。

请注意索引中零文档的边缘情况,但是......

希望这有帮助,