Indexation de contenus multi-langue sur Rails3 avec Sphinx et Globalize3

Ruby On Rails
Par mick
16 novembre 2011
sphinx

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 :

[ruby]
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
[/ruby]

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.

[ruby]
gem ‘globalize3’ # à placer dans le Gemfile
[/ruby]

Ensuite, il faut indiquer au modèle Actuality à qui nous allons traduire un certain nombre de ces attributs

[ruby]
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
[/ruby]

Pour finir, il faut modifier la structure de la base de données pour ajouter la table contenant les attributs traduits

[ruby]
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
[/ruby]

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 :

[ruby]
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
[/ruby]

Désormais comment utiliser les nouveaux index définis ? Nous pouvons tout simplement indiquer à la méthode search sur quel index rechercher.

[ruby]
Actuality.search "*#{q}*" , :index => "actuality_fr"
Actuality.search "*#{q}*" , :index => "actuality_de"
[/ruby]

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

Retrouvez-nous sur :

Ajouter un commentaire

Articles similaires