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 开发者_如何学Pythonif 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?)
精彩评论