2013-03-23 79 views
5

我正在使用Lucene 4.2并正在执行结果分页。Lucene 4分页

IndexSearcher.searchAfter提供了一种实现“下一页”功能的有效方式,但实现“上一页”或甚至“上页”功能的最佳方式是什么?例如没有IndexSearcher.searchBefore

我正在考虑确定给定页面大小的页面总数,并保持ScoreDoc[]阵列跟踪每个页面的“之后”ScoreDoc(该数组将填充为页面结果)。这将允许我使用“最接近的”ScoreDoc用于IndexSearcher.searchAfter(或在最坏情况下为零)。

这是否有意义?有更好的方法吗?

+0

嗨,你能解释一下在lucene 4.x和我也面临同样的问题的分页。 – 2014-02-04 12:23:49

+0

我一直在使用上面第三段讨论的方法。除了非常深的分页(没有意外),它表现相当好。 – hudsonb 2014-02-11 11:38:07

回答

11

我一直在使用Lucene 4.8,并一直致力于包含分页的REST接口。 我的解决方案是使用TopScoreDocCollector并调用topDocs(int startIndex,int numberOfhits)方法。起始索引是通过将基于零的页码乘以命中数来计算的。

... 
DirectoryReader reader = DirectoryReader.open(MMapDirectory.open(java.io.File(indexFile)); 
IndexSearcher searcher = new IndexSearcher(reader); 
TopScoreDocCollector collector = TopScoreDocCollector.create(MAX_RESULTS, true); // MAX_RESULTS is just an int limiting the total number of hits 
int startIndex = (page -1) * hitsPerPage; // our page is 1 based - so we need to convert to zero based 
Query query = new QueryParser(Version.LUCENE_48, "All", analyzer).parse(searchQuery); 
searcher.search(query, collector); 
TopDocs hits = collector.topDocs(startIndex, hitsPerPage); 
... 

因此,我的REST接口接受每个页面的页码和点击次数作为参数。 所以前进或后退就像提交一个新的请求一样简单,页面的适当值

+0

谢谢Jaimie,我喜欢这种方法。 – hudsonb 2014-07-02 14:54:50

4

我同意Jaimie解释的解决方案。但我想指出你必须注意的另一个方面,这有助于理解搜索引擎的一般机制。

使用TopDocCollector,您可以在结果按照分数或其他排序标准进行排序之前,定义与您的搜索查询匹配的匹配数量。

请看下面的例子:

collector = TopScoreDocCollector.create(9999, true); 
searcher.search(parser.parse("Clone Warrior"), collector); 
// get first page 
topDocs = collector.topDocs(0, 10); 
int resultSize=topDocs.scoreDocs.length; // 10 or less 
int totalHits=topDocs.totalHits; // 9999 or less 

我们告诉Lucene的这里收藏最多包含搜索短语“克隆战士” 9999个文件。这意味着,如果索引包含超过9999个包含该搜索短语的文档,收集器将在填充9999个匹配后停止!

这意味着,您选择MAX_RESULTS的次数越多,您的搜索结果越好。但是这只有在你期望有大量的点击时才有意义。 另一方面,如果您搜索“luke skywalker”并且您只会期待一次命中,那么MAX_RESULTS也可以设置为1.

因此,更改MAX_RESULTS会影响返回的scoreDocs,因为将执行排序在收集的点击。实际上,将MAX_RESULTS设置为足够大的大小,以便人类用户不会错过错过特定文档。这个概念完全违背了SQL数据库的行为,它始终考虑完整的数据池。

但lucene也支持另一种机制。您可以代替为收集器定义MAX_RESULTS,而是定义要等待结果集的时间量。例如,你可以定义你总是想在300ms后停止收集器。这是一个很好的方法来保护您的应用程序的性能问题。但是,如果您想确保计算所有相关文档,则必须将MAX_RESULTS的参数或最大等待时间设置为无限值。