Monday, October 17, 2011

Simple Pagination with Lucene Search Results

It is still not very straghtforward to do search result pagination in Lucene. The simplest way is still do the same search again and populate the next group of documents.

Firstly, create a Page object to calculate start and end index for certain page number. for example, page 3's record start from 20 to 29 if we show 10 records for each page.

public class Page implements Serializable {
 
 private int currentPageNo;
 private int start;
 private int end;
 private int totalCount;
 // default size is 10
 private int pageSize = 10;

 private int pageCount;

 public Page(int currentPageNo) {
  this.currentPageNo = currentPageNo;

 }

 public int getPageCount() {
  pageCount = totalCount / this.pageSize;
  if (totalCount % this.pageSize == 0)
   return pageCount;
  else
   return pageCount + 1;

 }

 public int getStart() {
  start = (currentPageNo - 1) * this.pageSize;
  return start;
 }

 public int getEnd() {
  end = getStart() + getPageSize();
  if (this.totalCount>0 && end > this.totalCount) {
   end = totalCount;
  }
  return end;
 }

 public int getCurrentPageNo() {
  return currentPageNo;
 }

 public void setCurrentPageNo(int currentPageNo) {
  this.currentPageNo = currentPageNo;
 }

 public long getTotalCount() {
  return totalCount;
 }

 public void setTotalCount(int totalCount) {
  this.totalCount = totalCount;
 }

 public int getPageSize() {
  return pageSize;
 }

 public void setPageSize(int pageSize) {
  this.pageSize = pageSize;
 }

}

Then we just load record in this Page's range:
Query query = new MatchAllDocsQuery();

  Page page = new Page(3);
  int end = page.getEnd();

  TopDocs docs = searcher.search(query, end);

  page.setTotalCount(docs.totalHits);
  System.out
    .println(docs.totalHits + " pageCount:" + page.getPageCount());

  for (int i = page.getStart(); i < page.getEnd(); i++) {

   ScoreDoc scoredoc = docs.scoreDocs[i];
   Document doc = searcher.doc(scoredoc.doc);

   System.out.println(doc.get("title"));

  }