在Lucene中,在不影响性能的情况下返回近似结果计数的公认方法是什么?

在Lucene中,在不影响性能的情况下返回近似结果计数的公认方法是什么?,lucene,Lucene,我希望我的用户的搜索结果包括一些关于给定搜索查询有多少匹配项的想法 但是,在对用户的搜索日志进行了一些研究和观察之后,我注意到日志查询速度与总结果数之间存在直接的相关性,并确定这是因为我正在访问totalHits属性,它显然必须迭代整个结果集才能返回值 我很乐意返回一个近似值,甚至可能只是一个数量级,表明有多少结果可用,但我看不出是否有任何好的方法可以在不明显影响性能的情况下计算这个值。我真的不想只是在用户面前转储一个看似无底洞的结果集,而不向他们提供任何关于他们的搜索匹配了多少结果的粗略概念

我希望我的用户的搜索结果包括一些关于给定搜索查询有多少匹配项的想法

但是,在对用户的搜索日志进行了一些研究和观察之后,我注意到日志查询速度与总结果数之间存在直接的相关性,并确定这是因为我正在访问
totalHits
属性,它显然必须迭代整个结果集才能返回值

我很乐意返回一个近似值,甚至可能只是一个数量级,表明有多少结果可用,但我看不出是否有任何好的方法可以在不明显影响性能的情况下计算这个值。我真的不想只是在用户面前转储一个看似无底洞的结果集,而不向他们提供任何关于他们的搜索匹配了多少结果的粗略概念


有什么建议吗?

首先,我们应该知道您希望为哪种查询执行此操作。例如,有一种非常快速的方法可以找出有多少文档包含任何具体术语(术语的docFreq)。因此,假设您有三个术语的连词,您可以使用三个docfreq中最小的一个进行近似计算。

对于布尔查询,您可以尝试近似计算:

  • | A或B |/| D |=(| A |/| D |)+(| B |/| D |))/2
  • | A和B |/| D |=(| A |/| D |)*(| B |/| D |)
其中,
A
B
是两个术语,
|D |
是文档总数。这基本上是在假设独立

您可以使用
rewrite
方法将任何查询重写为布尔查询

实际上没有更好的方法,但我发现这个假设在实践中并不坏。如果你有一个非常少的文件,它可能会给出错误的答案

编辑:正如jpountz指出的,我对OR的计算是错误的。应该是:

P(A U B) = 1 - P(~(AUB)) 
         = 1 - P((~A) & (~B))
         = 1 - P(~A)P(~B)
         = 1 - (1 - P(A))(1 - P(B))
         = 1 - (1 - P(A) - P(B) + P(A)P(B))
         = P(A) + P(B) - P(A)P(B)

Lucene的最新版本有一个专门用于计算计数的收集器,名为

它通常比其他收集器更快,因为:

  • ,
  • 它不需要计算分数
  • 它不构建顶级匹配的数组

关于
totalHits
:这只是lucene在完成搜索后设置的值。访问该属性不会做任何额外的工作,当然也不会迭代所有结果

Lucene在进行搜索时总是设置这个(并且知道总共有多少个结果)。它需要这样做,以便为您提供请求的前N个结果(根据您指定的分数或排序字段)

因此,在某些情况下,搜索速度很慢

您是否检查过哪些查询比较慢? 慢速和大量结果的组合表明存在某种通配符/模糊查询

有关提高搜索速度的一般信息,请访问


基于您的lucene-2.9.2标签,我建议您首先尝试升级到最新版本(如果可能),然后再次测量。自2.9.2以来,有很多变化/改进

这里缺少一些东西。。。我想你也必须用| D |分开左手边。@Marko:你说得对,我错了。我会更新答案的。顺便说一句,我在想你的方法。。。对于经常形成短语的查询词来说,独立性不是一个危险的假设吗?我认为在实践中,用最不常用的术语作为度量标准会给出上界,而度量标准会给出下界。只有在术语实际上是反相关的情况下,真正的命中率才会更低,我认为这在实践中是非常罕见的。@Xodarap为什么在OR的情况下你要除以2?@Marko:有趣的是,这对我来说很有效,但可能是我的用户不感兴趣。我对比较这些方法的任何数据都非常感兴趣。