2010-11-12 39 views
6

J'ai un site où les utilisateurs vont d'abord entrer leurs critères de recherche. La recherche combine des données provenant de 2 sources, dont l'une n'est pas une base de données. Les résultats de la recherche sont généralement assez grands pour être paginés.Mise en cache des données dans les grails

Étant donné que la requête initiale est coûteuse, je souhaite mettre en cache les résultats de la recherche si les critères de recherche ne changent pas pour les pages vues suivantes.

Ma méthode actuelle ressemble à:

def search(criteriaMap, offset, pagesize) 

Quelle est la meilleure façon de mettre en cache les résultats de la recherche dans Groovy/Grails? Comment devrais-je expirer les résultats de la recherche? Remarque, je vois qu'il existe un plugin springcache mais je ne suis pas sûr que cela fonctionnera pour les résultats paginés. Je sais aussi que grails est empaqueté avec ehcache mais je n'ai pas vu d'API à laquelle j'ai directement accès, je l'ai seulement vu utilisé pour la mise en cache de 2nd niveau avec GORM.

Mise à jour: J'ai pris part à la solution de @ mfloryan pour résoudre ce problème.

J'ai créé deux méthodes dans le SearchService:

@Cacheable("searchCache") 
def searchResults(uid, trimmedParams) 
def trimParams(params) 

(One est mis en cache et l'autre non.)

Mon code dans le 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] 

En conséquence, j'ai invoqué le service de recherche avec une liste rognée de paramètres qui ne comprennent pas Ude paging params. Les résultats de recherche mis en cache peuvent être renvoyés.

searchController prend en charge le paging.

note: Je n'ai pas mis en cache les résultats de mise en veille prolongée parce que je finirais par doubler les données dans le cache. J'ai seulement caché les résultats combinés de searchService.searchResults (qui frappe une API REST et ma base de données locale)

Répondre

5

Premièrement, si vous voulez cacher la requête, alors peut-être que l'utilisation du cache de requêtes Hibernate est un bon début (Set cache:true in le mappings et passer cache: true au executeQuery)

Utilisation du SpringCache plug-in vous permettra de mettre en cache toute la réponse du contrôleur. Tout ce que vous devez faire est de décorer le contrôleur comme ça: @Cacheable("searchMethodCache") ou seulement décorer les méthodes individuelles que vous voulez les résultats de la mise en cache. Le cache enregistre la réponse par chaîne de requête, de sorte qu'il devrait fonctionner correctement avec la pagination. L'annotation @CacheFlush permet de définir quand le cache doit être effacé.

Le EH Cache est lui-même configuré dans grails-app/conf/spring/resources.groovy

- MISE À JOUR -

Après vous faire des commentaires, je commence à soupçonner votre peut-être penser d'une solution légèrement différente. Il y a donc une requête qui renvoie une liste de résultats et cette liste est ensuite paginée et affichée.Avec l'approche standard de Grails, Hibernate va générer une requête pour chaque page (renvoyant un sous-ensemble de la liste complète et exécutant ainsi la requête potentiellement coûteuse une fois pour chaque page). Vraisemblablement, vous voulez que la requête soit exécutée une fois - pour retourner le jeu de résultats complet qui est mis en cache et ensuite servir des pages individuelles de l'it. Si tel est le cas, autant que je sache, vous devrez faire une recherche manuelle des résultats depuis le cache Hibernate ou mettre le jeu de résultats ailleurs (contexte de session?)

+0

Comment le widget de pagination interagirait-il avec ceci? puis-je vider le cache en fonction de l'heure ou de la commande FIFO? – Tihom

+0

Aller à une page différente modifie la chaîne de requête afin que la réponse différente soit mise en cache et servie. Le cache expire automatiquement, donc pas besoin de vidage explicite en fonction de l'heure. Il suffit de le configurer dans Config.groovy sous sprigcache/caches/[cacheName]/timeToLive = ... – mfloryan

+0

Je voudrais éviter la requery pour différentes pages. Comment je fais ça? – Tihom