7

我知道它可以在 Lucene 索引中获取最热门的术语,但是有没有办法根据 Lucene 索引的子集来获取最热门的术语?

即特定日期范围内的文档索引中的顶级术语是什么?

4

2 回答 2

6

理想情况下,在某处会有一个实用程序来执行此操作,但我不知道有一个。但是,以合理有效的方式“手动”完成此操作并不难。我假设您已经有一个Query和/或Filter对象,您可以使用它来定义感兴趣的子集。

首先,在您的索引子集中的所有文档 ID 的内存中构建一个列表。您可以使用IndexSearcher.search(Query, Filter, HitCollector)它非常快速地执行此操作;该HitCollector 文档包含一个看起来应该可以工作的示例,或者您可以使用其他一些容器来存储您的文档 ID。

接下来,初始化一个空的 HashMap(或其他)以将术语映射到总频率,并通过IndexReader.getTermFreqVector为每个文档和感兴趣的字段调用其中一种方法来填充映射。三参数形式似乎更简单,但任何一个都应该没问题。对于三参数形式,您将创建TermVectorMapperwhomap方法检查是否term在地图中,frequency如果不在则将其与现有值相关联,如果是则添加frequency到现有值。确保在此过程TermVectorMapper中的所有调用中使用相同的对象getTermFreqVector,而不是为循环中的每个文档实例化一个新对象。isIgnoringPositions()您还可以通过覆盖和来加快速度isIgnoringOffsets();你的对象应该true为这两个返回。看起来像你的TermVectorMapper也可能被迫定义一种setExpectations方法,但不需要做任何事情。

构建地图后,只需按频率降序对地图项目进行排序,然后读出您喜欢的许多热门术语。如果您事先知道需要多少项,您可能更喜欢使用某种奇特的基于堆的算法来在线性时间内找到前k个项目,而不是使用 O( n log n ) 排序。我想普通的旧类型在实践中会很快。但这取决于你。

如果您愿意,可以通过直接HitCollector调用来组合前两个阶段。getTermFreqVector这当然应该产生同样正确的结果,并且直观地看起来它会更简单更好,但文档似乎警告说这样做可能比两遍方法慢很多(与 HitCollector 示例在同一页面上以上)。或者我可能误解了他们的警告。如果你觉得雄心勃勃,你可以尝试两种方式,比较,让我们知道。

于 2008-10-22T01:04:36.070 回答
1

计算 TermVectors 会起作用,但如果有很多文档要迭代,就会很慢。另请注意,如果您通过顶级术语表示 docFreq,则不要使用 TermFreqVector 中的计数,只需将术语计算为二进制即可。

或者,您可以迭代诸如方面计数之类的术语。对每个术语使用缓存过滤器;他们的BitSet可用于快速交叉点计数。

于 2011-10-26T01:23:35.740 回答