Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lucene 4 Pagination

I am using Lucene 4.2 and am implementing result pagination.

IndexSearcher.searchAfter provides an efficient way of implementing "next page" functionality but what is the best way to go about implementing "previous page" or even "go to page" functionality? There is no IndexSearcher.searchBefore for example.

I was considering determining the total number of pages given the page size and keeping a ScoreDoc[] array to track the "after" ScoreDoc for each page (the array would be populated as results are paged in). This would allow me to use the "closest" ScoreDoc for use in IndexSearcher.searchAfter (or null in the worst case).

Does this make sense? Is there a better approach?

like image 699
hudsonb Avatar asked Mar 23 '13 16:03

hudsonb


1 Answers

I've been using Lucene 4.8 and have been working on a REST interface which includes pagination. My solution has been to use a TopScoreDocCollector and call the topDocs(int startIndex, int numberOfhits) method. The start index is calculated by multiplying the zero based page number by the number of hits.

...
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);
...

So my REST interface accepts the page number and number of hits per page as parameters. So going forward or back is as simple as submitting a new request with the appropriate value for the page

like image 102
Jaimie Whiteside Avatar answered Sep 30 '22 13:09

Jaimie Whiteside