Développer avec RBS Change : [Recherche] Dates et intervalles de dates ?
-
27/12/2011 17:48 Bonjour,
Dans le moteur de recherche utilisant SolR, je cherche à filtrer mes résultats par date de création : dans mon formulaire de recherche avancée, j'ai ajouté 2 champs ("de ... à ..."). Je souhaite retourner les documents créés entre les 2 dates saisies, ou après la première date (si la seconde est vide), ou avant la seconde date (si la première est vide).
Je ne vois pas du tout comment faire. Ma seule piste est une dateFieldInstance, mais je ne vois pas comment m'en servir.
Merci d'avance -
48949.2 en réponse à 48949.1 écrit par David Guillot
04/01/2012 12:21 Alors il y a plusieurs choses à prendre en compte à ce niveau :
1) par défaut la date de création n'est pas indexée (seule la date de modification l'est), il faut donc ajouter son indexation. En 3.5.3 ce sera faisable simplement en injectant l'IndexService et en surchargeant la méthode completeFrontIndexDocument (introduite par le ticket Impossible d'agir globalement pour ajouter des infos à l'indexation des documents)./** * @param indexer_IndexedDocument $indexedDocument * @param f_persistentdocument_PersistentDocument $document */ protected function completeFrontIndexDocument($indexedDocument, $document) { $indexedDocument->setDateField('creation_date', date_Calendar::getInstance($document->getCreationDate())); }
2) ensuite voilà un exemple de requête renvoyant les document créés dans les 7 derniers jours :$upper = date_Calendar::now(); $lower = date_Calendar::now()->sub(date_Calendar::DAY, 7); $query = indexer_QueryHelper::orInstance(); $query->add(new indexer_RangeQuery(indexer_Field::getDateFieldName('creation_date'), $lower, $upper)); $query->setFirstHitOffset(0); $query->setReturnedHitsCount(100); $searchResults = indexer_IndexService::getInstance()->search($query);Où upper et lower sont respectivement les bornes supérieures et inférieures de l'intervalle. L'une ou l'autre pouvant valoir null si l'on ne veut qu'une seule borne.Édité par Gaël Port 04/01/2012 13:54
-
05/01/2012 15:57 Merci !
Alors j'ai une bonne et une mauvaise nouvelle :
- La bonne : la recherche par date (et intervalles de dates) fonctionne très bien, et je me suis rendu compte que la date la plus pertinente pour moi est la sortable_date, déjà indexée pour tous les documents ; donc je n'ai pas eu besoin d'injecter l'IndexService pour cette fonctionnalité
- La mauvaise : pour un autre besoin j'ai essayé d'injecter l'IndexService (via aop.xml, caop et ua) et de surcharger la méthode completeFrontIndexDocument, mais malheureusement ma méthode n'est jamais atteinte : en effet, l'IndexService de base fait appel à $this->completeFrontIndexDocument, et appelle donc la méthode présente dans sa propre classe, pas la mienne. Comment faire ?
Merci d'avance -
48949.4 en réponse à 48949.3 écrit par David Guillot
06/01/2012 09:03 En théorie quand vous passez par l'AOP, la classe est réécrite, donc au final l'IndexService finalement utilisé aura bien votre implémentation de la méthode.
Par contre, un point à garder à l'esprit c'est que lors d'un remplacement de classe par AOP, il faut impérativement relancer un compile-aop (caop) après chaque modification du code PHP de la classe remplaçante (et également de la classe remplacée si ça devrait arriver mais il n'y a pas de raison : le remplacement de classe étant utilisé justement pour éviter cela), afin de régénérer la classe réécrite.Édité par Gaël Port 06/01/2012 09:05
-
Alors en fait j'ai trouvé d'où vient mon problème : ma méthode completeFrontIndexDocument n'est jamais appelée car l'objet IndexService instancié est de la classe indexer_IndexService_replaced0, qui contient la méthode static getInstance(). J'aimerais pouvoir surcharger cette méthode afin d'instancier un objet de ma classe, mais la méthode getInstance() est également final. Que faire ?
-
48949.6 en réponse à 48949.5 écrit par David Guillot
06/01/2012 11:25 Voici le correctif que je propose dans la classe indexer_IndexService :public final static function getInstance() { if (null === self::$instance) { $newInstance = self::getServiceClassInstance('indexer_IndexService');
(replacement du nom automatique de la classe par le nom en dur de la classe) -
48949.7 en réponse à 48949.6 écrit par David Guillot
06/01/2012 16:09 Ah j'avais pas vu que la méthode était finale... Dans ce cas le plus simple est de faire de l'injection de service. Ainsi la classe ne sera pas réécrite mais le getInstance retournera une instance de la classe injectée (grâce à l'appel à getServiceClassInstance).Édité par Gaël Port 06/01/2012 16:10
-
06/01/2012 16:46 OK merci ça marche beaucoup mieux comme ça, et sans modification du service d'origine !!

