2

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

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

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

有什么建议么?

4

4 回答 4

3

使用布尔查询,您可以尝试近似:

  • |A or B| / |D| = ((|A| / |D|) + (|B| / |D|)) / 2
  • |A and B| / |D| = (|A| / |D|) * (|B| / |D|)

其中AB是两个术语,和|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)
于 2012-04-09T20:12:48.680 回答
2

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

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

于 2012-04-10T07:47:38.460 回答
1

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

于 2012-04-09T19:51:45.007 回答
0

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

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

所以实际上在某些情况下搜索很慢。

你有没有检查过什么样的查询很慢?缓慢和大量结果的组合可能表明存在某种通配符/模糊查询。

可以在http://wiki.apache.org/lucene-java/ImproveSearchingSpeed找到提高搜索速度的一般信息

根据您的 lucene-2.9.2 标签,我建议您首先尝试升级到最新版本并再次测量。自 2.9.2 以来有很多变化/改进

于 2012-04-10T17:29:51.500 回答