I have a site where users will first enter their search criteria. The search combines data from 2 sources, one of which is not a database. The search results are generally large enough to be paged.
Since the initial query is expensive, I would like to cache the search results if the search criteria doesn't change for subsequent page views.
My current method looks like:
def search(criteriaMap, offset, pagesize)
What is the best way of caching the search results in groovy/grails? How would I expire the search results?
Note, I see there is a springcache plugin but I am not sure if this will work for paged results. I also know that grails is packaged with ehcache but I haven't seen an API I directly have access to, I have only seen it used for 2nd level caching with GORM.
Update: I took part of @mfloryan's solution to solve this.
I created two methods in the searchService:
@Cacheable("searchCache")
def searchResults(uid, trimmedParams)
def trimParams(params)
(One is cached and the other is not.)
My code in the searchController:
def trimmedParams = searchService.trimParams(params)
def results = searchService.searchResults(trimmedParams)
//Page results
results = HelperService.pageResults(results, params.offset, params.max)
[results: results, searchParams : trimmedParams]
As a results, I invoked the search service with a trimmed list of parameters that do not include paging params. The cached search results can be returned.
The searchController takes care of the paging.
note: I didn't cache the hibernate results because I would end up with double the data in the cache. I only cached the combined results from searchService.searchResults (which hits a REST API and my local database)
Firstly, if you want to cache the query, then perhaps using the Hibernate query cache is a good start (Set cache:true
in the mappings
and pass cache: true
to the executeQuery
)
Using the SpringCache plug-in will allow you to cache the entire response from the controller. All you would need to do is decorate the controller like that: @Cacheable("searchMethodCache")
or only decorate individual methods that you want results of cached. The cache will save response by query string so it should work well with paging.
The @CacheFlush
annotation allows to set when the cache should be cleared.
The EH Cache itself is configured in grails-app/conf/spring/resources.groovy
-- UPDATE --
Following you comment I begin to suspect your might be thinking of a slightly different solution. So there is a query that returns a list of results and that list is then paged and displayed. With standard Grails approach Hibernate will generate one query for each page (returning a subset from the full list thus running the potentially expensive query once for each page). Presumably you want the query to be run once - to return the full result set that gets cached and then serve individual pages from the it. If that's the case, far as I know, you will have to page the results manually either from the Hibernate cache or caching the result set somewhere else (Session context?)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With