我知道有可能在Lucene索引中获得最高项,但有没有办法根据Lucene索引的子集获得最高项?
即。索引中某些日期范围内的文档中的最高术语是什么?
答案 0 :(得分:5)
理想情况下,某处有一个实用工具,但我不知道。然而,以合理有效的方式“手动”完成这项工作并不困难。我假设您已经有一个Query
和/或Filter
对象可用于定义感兴趣的子集。
首先,在内存中构建索引子集中所有文档ID的列表。您可以使用IndexSearcher.search(Query, Filter, HitCollector)
来快速完成此操作; HitCollector
documentation包含一个似乎应该有效的示例,或者您可以使用其他容器来存储您的文档ID。
接下来,初始化一个空的HashMap(或其他)以将术语映射到总频率,并通过为每个感兴趣的文档和字段调用IndexReader.getTermFreqVector
方法之一来填充地图。三参数形式似乎更简单,但要么两者都应该没问题。对于三参数表单,您需要TermVectorMapper
map
方法检查地图中是否term
,如果没有frequency
,则添加frequency
如果是,则{1}}到现有值。确保在此过程中对TermVectorMapper
的所有调用使用相同的getTermFreqVector
对象,而不是为循环中的每个文档实例化一个新对象。您还可以通过覆盖isIgnoringPositions()
和isIgnoringOffsets()
来加快速度。你的对象应该为这两个对象返回true
。您的TermVectorMapper
似乎也可能被迫定义setExpectations
方法,但该方法不需要做任何事情。
构建地图后,只需按降序频率对地图项进行排序,然后读出您喜欢的多个顶级字词。如果你事先知道你想要多少个术语,你可能更愿意做一些花哨的基于堆的算法来在线性时间内找到顶部的 k 项而不是使用O( n log n )排序。我想,在实践中,这种简单的老式会很快。但这取决于你。
如果您愿意,可以直接调用HitCollector
getTermFreqVector
来合并前两个阶段。这当然应该产生同样正确的结果,并且直观地看起来它会更简单和更好,但是文档似乎警告说,这样做可能比两遍方法慢得多(在与HitCollector示例相同的页面上)以上)。或者我可能会误解他们的警告。如果你有野心,你可以尝试两种方式,比较,并让我们知道。
答案 1 :(得分:0)
计算TermVectors会有效,但如果要迭代很多文档,它们会很慢。另请注意,如果您的意思是docFreq的顶级术语,那么请不要在TermFreqVector中使用计数,只需将术语计为二进制。
或者,您可以迭代像facet计数这样的术语。每个学期使用cached filter;他们的BitSets可用于快速交叉计数。