Recherche en texte intégral dans Rails

Ce que vous allez créer

introduction

La recherche d'enregistrements est une exigence courante dans les applications Web. Il est généralement nécessaire de permettre aux utilisateurs d’accéder rapidement aux données qu’ils souhaitent à partir d’enregistrements volumineux. Bien qu'il soit possible de le faire en utilisant de simples requêtes SQL, il est parfois plus efficace d'utiliser un moteur de recherche..

Solr est une plateforme de recherche populaire issue du projet Apache Lucene. Ses principales fonctionnalités comprennent la recherche en texte intégral, la mise en évidence des occurrences, la recherche par facettes, l'indexation en temps quasi réel, la mise en cluster dynamique, l'intégration de la base de données, la gestion de documents détaillés et la recherche géospatiale. Dans ce didacticiel, nous étudierons la possibilité d'effectuer une recherche en texte intégral à l'aide de Sunspot, une bibliothèque permettant l'intégration de Solr dans des applications ruby..

Configuration du projet

J'ai créé une application simple sur Github que je vais utiliser ici au lieu de commencer avec un nouveau projet. L'application affiche une liste de produits avec leur nom, leur image, leur prix et leur description. J'ai inclus quelques données de base afin que vous puissiez exécuter rake db: seed si vous ne voulez pas entrer les données vous-même. L'application utilise Paperclip pour les images jointes et, comme j'utilise le redimensionnement, ImageMagick devra être installé sur votre système. Vous aurez également besoin du moteur d'exécution Java installé sur votre ordinateur pour poursuivre le didacticiel..

L'image ci-dessous montre l'application. Le formulaire de recherche en haut ne fait rien pour le moment, mais nous allons permettre à l'utilisateur de faire une recherche parmi les produits et d'obtenir des résultats basés non seulement sur le nom du produit, mais également sur sa description..

Recherche

Nous allons commencer par inclure les gemmes Sunspot et Solr dans notre Gemfile. Pour le développement, nous utiliserons le sunspot_solr bijou fourni avec une distribution Solr préemballée, nous n’avons donc pas besoin de l’installer séparément.

groupe 'sunspot_rails' de gem: développement ne gem 'sunspot_solr' fin

Courir installation groupée puis exécutez la commande suivante pour générer le fichier de configuration de Sunspot.

les rails génèrent sunspot_rails: install

Cela crée le /config/sunspot.yml fichier qui indique à votre application où trouver le serveur Solr.

Pour configurer les objets à indexer, ajoutez un bloc interrogeable aux objets. Dans le projet de démarrage, nous avons un modèle de produit avec les champs nom, prix, description et photo. Nous allons permettre d'effectuer une recherche en texte intégral sur les champs de nom et de description. Dans /models/product.rb ajouter:

interrogeable do texte: nom,: description fin

Démarrez le serveur Solr en lançant:

rake tache solaire: solr: start

Sunspot indexe les nouveaux enregistrements que vous créez, mais si vous en avez déjà dans la base de données, exécutez rake tache solaire: réindexer de les indexer.

Nous ajoutons ensuite le code dans le contrôleur de produits qui prendra les entrées de l'utilisateur et le transmettra au moteur de recherche. Dans le code ci-dessous, nous appelons chercher sur le modèle du produit et passez dans un bloc. Nous appelons le texte intégral méthode dans le bloc et passez dans la chaîne de requête que nous voulons être recherché. Vous pouvez utiliser ici plusieurs méthodes pour spécifier les résultats de recherche souhaités. Les résultats de la recherche sont ensuite affectés à @des produits qui sera disponible à notre avis.

def index @query = Product.search faire le texte intégral params [: search] end @products = @ query.results end

Exécutez l'application et vous devriez maintenant être capable de chercher parmi les produits disponibles. 

Solr fera une recherche insensible à la casse dans les noms de produits et les descriptions à l'aide du mot ou de la phrase entrée. Vous pouvez faire en sorte qu'un champ ait plus de poids qu'un autre pour améliorer la pertinence de vos résultats de recherche. Ceci est fait avec le renforcer méthode à laquelle est transmise une valeur qui détermine la priorité attribuée aux différents champs. Le champ avec la valeur la plus élevée aura plus d'importance. 

Dans notre application, nous pouvons spécifier les produits dont le nom de la chaîne recherchée doit être noté plus haut. Nous faisons cela en faisant les changements suivants dans /models/product.rb.

texte consultable: nom,: boost => 2 texte: description fin

Réindexer les enregistrements avec rake tache solaire: réindexer et maintenant les résultats avec le terme recherché dans le nom du produit seront placés plus haut que ceux avec le terme dans la description. Vous pouvez ajouter plus de disques pour tester ceci.

Navigation à facettes

La navigation par facettes est un moyen de parcourir les données de recherche au moyen de divers ensembles d'attributs associés. Par exemple, dans notre application, nous pouvons classer les recherches de produits par gamme de prix et donner le nombre de chaque gamme..

Tout d'abord ajouter des prix à la consultable méthode en /models/product.rb

texte consultable: nom,: boost => 2 texte: description double: fin de prix

Alors appelez facette dans le contrôleur. Les prix des produits seront différenciés par intervalles de 100,00 $. Ici, nous supposons que tous les produits coûtent moins de 500 $.

def index @query = Product.search faire le texte intégral params [: recherche] facette: price,: range => 0… 500,: range_interval => 100 avec (: price, Range.new (* params [: price_range] .split ( "…") .Map (&: to_i))) si params [: range_prix] .present? end @products = @ query.results end

Dans le fichier de vue, collez le texte suivant à l'endroit où vous souhaitez voir les résultats avec facettes.

Résultats de la recherche

    <% for row in @query.facet(:price).rows %>
  • <% if params[:price_range].blank? %> <%= link_to row.value, :price_range => row.value,: search => params [: search]%> (<%= row.count %>) <% else %> <%= row.value %> (<%= link_to "X", :price_range => nil%>) <% end %>
  • <% end %>

Désormais, lorsque vous recherchez un terme, une liste de facettes indiquant le nombre de résultats compris dans chaque gamme de prix apparaît. Dans notre exemple d'application, si vous recherchez le mot "caméra", vous verrez la liste suivante.

100,0… 200,0 (2) 200,0… 300,0 (1) 300,0… 400,0 (1)

Chaque article est un lien et lorsque vous cliquez dessus, vous obtenez une liste des produits qui correspondent à votre recherche et qui entrent également dans la fourchette de prix sur laquelle vous avez cliqué.. 

Le lien transmet la requête de recherche d'origine et la plage choisie à l'action d'index. Puisqu'il passe la gamme comme une chaîne, nous utilisons Range.new (* params [: range_prix] .split ("…") .map (&: to_i)) pour le reconvertir en plage. Vous pouvez utiliser des instructions conditionnelles pour générer davantage de liens conviviaux, tels que 100 $ à 199 $ (2) au lieu de 100,0… 200,0 (2) mais nous n'entrerons pas dans cela ici.

Configurations avancées

Il existe quelques configurations supplémentaires que vous pouvez faire sur Solr pour personnaliser son fonctionnement. Par défaut, Sunspot effectue une recherche en texte intégral en divisant la chaîne de recherche en jetons basés sur des espaces et d'autres caractères de délimitation à l'aide d'un tokenizer intelligent appelé StandardTokenizer. Ensuite, les jetons sont en minuscule et les mots exacts sont recherchés.

Cela peut parfois convenir, mais vous pouvez également configurer le moteur de recherche de manière à permettre les erreurs humaines ou à permettre des requêtes qui ne sont pas trop strictes. Par exemple, vous pouvez vouloir fournir des synonymes au moteur afin que, lorsque l'utilisateur n'entre pas le texte exact qui se trouve dans vos enregistrements, il puisse toujours trouver des résultats similaires. Un exemple de ceci est que vous pourriez avoir un article intitulé «ipod» dans vos enregistrements. Vous pouvez fournir des synonymes tels que "iPod", "i-pod" et "i pod" pour augmenter les chances des utilisateurs de trouver les données..

Une autre fonctionnalité utile que vous pourriez ajouter est la tige, ce qui permettra à Solr de faire correspondre différents mots avec la même racine. Par exemple, si l'utilisateur saisissait «run», il obtiendrait des résultats avec «run» et «running». Ou s'ils cherchaient «marcher», les résultats incluraient des données contenant «marcher», «marcher», «marcher», etc..

Les paramètres Solr se trouvent dans solr / conf / schema.xml et c'est le fichier à modifier pour changer la configuration du serveur. Cela sort du cadre de ce tutoriel, mais pour plus d'informations à ce sujet, consultez le post avancé de configuration de texte intégral et le wiki Solr.

Conclusion

Maintenant, pour terminer, arrêtez le serveur Solr en lançant:

rake tache solaire: solr: stop

Nous avons examiné comment utiliser le joyau Sunspot pour utiliser le moteur de recherche Solr dans une application Rails. Outre les paramètres que nous avons utilisés, vous pouvez en utiliser beaucoup plus pour personnaliser vos résultats de recherche. Assurez-vous de vérifier le fichier Lisez-moi pour plus d'options.

Solr vous offre un type de recherche difficile à réaliser avec des requêtes SQL classiques. Pour les applications simples, avec un petit nombre d'enregistrements de base de données, les requêtes SQL se passeront sans grande perte de performances. Mais si vous voulez quelque chose d'évolutif, alors il vaut la peine de chercher dans Solr ou d'autres moteurs de recherche disponibles..