【问题标题】:Fastest way to count all results in Lucene (java)在 Lucene (java) 中计算所有结果的最快方法
【发布时间】:2011-06-22 14:01:53
【问题描述】:

在 Lucene 中计算给定查询的所有结果的最快方法是什么?

  1. TopDocs.totalHits
  2. 使用 QueryFilter 实现和管理过滤器
  3. 实现自定义“计数”收集器。这只是在 collect(int doc) 方法中增加一个计数,并为 acceptDocOutOfOrder() 方法返回 true。所有其他方法都是 NOOPS。

由于 1. 将对所有文档进行评分,并且 2. 由于加载 FieldCache 可能会受到前期打击,我假设答案是 3。Lucene 没有提供这样的收集器似乎很奇怪盒子?

【问题讨论】:

    标签: java search lucene performance


    【解决方案1】:

    你说得对,#3 会更快,但我不认为这是因为得分。有一种更快的方法,如果您不关心这背后的原因,请跳到底部。

    #1 的性能损失来自 TopDocs 收集器会将文档保留在优先级队列中,这意味着您将浪费一些时间按分数对它们进行排序。 (你也会消耗一些内存,但由于你只存储了一堆 int+float 对,它可能非常少。)

    至于为什么 Lucene 不提供开箱即用的功能:您通常不希望找到所有结果。这就是为什么当你搜索时,你说只找到前 n 个结果。为此有strong theoretical reasons。甚至 Google 都说“显示 25 个大约 n 个结果。”

    所以我对您的建议如下:如果您有合理数量的结果,那么使用TopDocs.totalHits 在性能方面不会太差。如果totalHits 方法给您带来问题,我认为自定义收集器不会好得多。 (TopDocs.totalHits 将在 n log n 时间内运行,自定义收集器将是线性的。根据您的设置,log n 系数可能相关,也可能不相关。)

    所以,如果你绝对需要这个功能,而TopDocs.totalHits 太慢,我建议你查看搜索词的文档频率。您可以假设频率是独立的(因此 p(A 和 B)=p(A)*p(B))并从那里做出很好的猜测。它会非常快,因为它只是对每个术语的恒定时间查找。

    【讨论】:

    • 感谢您的回答。在这个阶段,我们将使用 TotalHitCountCollector。我们的数据集仍然小到可以准确计数。不过,我会牢记您所描述的频率方法——这确实听起来是最快的方法。
    • 我想知道 Google 是如何做到这一点的。显然,它并没有真正返回“前 25 名”结果。如果是,那么它应该知道结果总数作为检查所有其他结果以发现它们不在前 25 名中的副作用。我的理论是它返回 25 基本上是任意的“值得最高”的结果。
    【解决方案2】:

    【讨论】:

    • 谢谢。看起来它会出现在即将发布的 Lucene 版本中?
    • 是的,这是即将发布的 3.x 版本的分支(下一个目标是 3.1)
    猜你喜欢
    • 1970-01-01
    • 2017-10-24
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2013-03-05
    • 1970-01-01
    • 2019-06-25
    • 2010-10-08
    相关资源
    最近更新 更多