Sphinx est un serveur de recherche full text permettant d’indexer et de rechercher dans des données stockées soit dans des bases de données SQL, no SQL ou alors dans un système de fichiers.
Il peut facilement s’intégrer à une application Ruby On Rails via la gem Thinking Sphinx. On définit alors dans les modèles tous les attributs qui doivent être indexés. Cela fonctionne parfaitement lorsque notre application utilise une seule et unique locale.
Prenons l’exemple d’une application dans laquelle nous avons défini un modèle Actuality :
class Actuality < ActiveRecord::Base validates :title, :presence => true validates :body, :presence => true define_index do indexes :title indexes :summary indexes :body set_property :delta => true end end
Que se passe-t’il donc lorsque l’application développée est internationalisée et que les traductions des contenus stockés en base doivent être indexés par locale ?
Avant d’arriver au résultat final, jetons un coup d’oeil rapide sur la gestion de la traduction des contenus.
Nous utilisons pour cela la gem Globalize3 qui permet de stocker les traductions de certains attributs d’un modèle dans une table à part.
gem 'globalize3' # à placer dans le Gemfile
Ensuite, il faut indiquer au modèle Actuality à qui nous allons traduire un certain nombre de ces attributs
class Actuality < ActiveRecord::Base translates :title, :body validates :title, :presence => true validates :body, :presence => true define_index do indexes :title indexes :body set_property :delta => true end end
Pour finir, il faut modifier la structure de la base de données pour ajouter la table contenant les attributs traduits
class AddTranlationsToActualities < ActiveRecord::Migration def self.up Actuality.create_translation_table! :title => :string, :body => :text end def self.down Actuality.drop_translation_table! end end
Maintenant que les attributs title et body d’Actuality sont traduits via Globalize3, nous pouvons définir les index associés à chaque locale en précisant que les attributs qui doivent être indexés sont ceux de la table translations associée à notre modèle et que nous utilisons un filtre de sélection différent pour chaque locale :
class Actuality < ActiveRecord::Base translates :title, :body validates :title, :presence => true validates :body, :presence => true define_index('actuality_fr') do indexes translations.title, :as => :title indexes translations.body, :as => :body where "actuality_translations.locale='fr'" set_property :delta => true end define_index('actuality_de') do indexes translations.title, :as => :title indexes translations.body, :as => :body where "actuality_translations.locale='de'" set_property :delta => true end end
Désormais comment utiliser les nouveaux index définis ? Nous pouvons tout simplement indiquer à la méthode search sur quel index rechercher.
Actuality.search "*#{q}*" , :index => "actuality_fr" Actuality.search "*#{q}*" , :index => "actuality_de"
En conclusion, il est possible très simplement dans Rails3 de créer un moteur de recherche basé sur Sphinx et recherchant des contenus en fonction de la locale de l’utilisateur.
Auteur : Michaël Mithouard
Ajouter un commentaire