Hippo Site Toolkit Query interface and pagination
Today an interesting question came from a developer of one of our implementation partners. He wanted to list items from our JCR repository and use pagination. In this post I tried to make a summary out of the conversation.
The query was:
HstQuery query =
getQueryManager().createQuery(requestContext, scope, filterBean);
Filter filter = query.createFilter();
filter.addContains(".", "my keywords");
query.setFilter(filter);
HstQuery queryResult = query.execute();
The developer tried to get a paged result and the total number of items with:
query.setOffset(0);
query.setLimit(10);
HippoBeanIterator hits = queryResult.getHippoBeans();
hits.getSize();
The result contained indeed 10 items but hits.getSize();
also returned 10. What’s going wrong? Ard Schrijvers explained:
If you use
setLimit(3)
, you will get at most 3 hits, but never more.getSize()
from thequeryResult
returns at most 3. Even if the search criteria matched hundreds of documents. If you useoffset(10)
and no limit,getSize()
returns just 10 hits less then without the offset.This limit is there to be used for performance, and suits for example very well "show last 3 agenda items on homepage".
If you need paging and only want 10 results, do not use
setLimit(int limit)
.What you do use, is just the query without
setLimit()
. Then you’ll get back aqueryResult
, from which you get aHippoBeanIterator
. This is a normalIterator
, with some extensions. A very important one is the methodskip(int skipNum)
.From the
HippoBeanIterator
, you can simply iterate the beans you need. Make sure you useskip(int skipNum)
to jump to the correct place. If the current page is 11 and pagesize is 20, setskipNum
to 220.Then fill your
List
in a for loop fromskipNum — skipNum + pageSize
.
What about performance?
The skip is propagated to the JCR
NodeIterator
. If you want to display item 100-110, and you useskip(100)
, still only 10 Beans will be created. JCR nodes for Beans 0-99 are not fetched.
What if you need the total number of hits?
Use
getSize()
. ThegetSize()
on the theHstQueryResultImpl
or on theHippoBeanIteratorImpl
does not actually populate the entire iterator withHippoBeans
. It is a call through the JCRNodeIterator
, which in JackRabbit is some lazy loading iterator, and, where thegetSize()
is propagated to the executed query, without fetching actual nodes.