X

Présentation de Laravel Scout | MattStauffer.com


Les outils de recherche ElasticSearch et Algolia ont gagné en popularité dans la communauté Laravel ces dernières années en tant qu’outils puissants pour indexer et rechercher vos données. Ben Corlett a fait un travail fantastique en présentant ElasticSearch à Laracon Eu 2014, et j’ai écrit une demande d’extraction à Laravel.com en introduisant l’indexation basée sur ElasticSearch pour les documents en 2015. Mais avant que mon PR ne soit fusionné, les gens d’Algolia l’ont pris et mis à jour pour utiliser à la place Algolia (plus rapide et avec une meilleure interface utilisateur !), et c’est ce que vous verrez aujourd’hui si vous recherchez la documentation de Laravel.

Si vous jetez un coup d’œil à ma demande d’extraction ou à la leur, vous verrez que ce n’est pas une mince tâche d’intégrer la recherche en texte intégral dans votre site. Algolia a depuis publié un produit gratuit appelé Algolia DocSearch qui facilite l’ajout d’un widget de recherche Algolia aux pages de documentation. Mais pour tout le reste, vous êtes toujours coincé à écrire l’intégration vous-même, c’est-à-dire jusqu’à maintenant.

Présentation de Laravel Scout

Scout est une solution de recherche en texte intégral basée sur un pilote pour Eloquent. Scout facilite l’indexation et la recherche du contenu de vos modèles Eloquent ; actuellement, il fonctionne avec Algolia et ElasticSearch, mais Taylor a demandé des contributions de la communauté à d’autres services de recherche en texte intégral.

Scout est un package Laravel distinct, comme Cashier, que vous devrez intégrer à Composer. Nous allons ajouter des traits à nos modèles qui indiquent à Scout qu’il doit écouter les événements déclenchés lorsque des instances de ces modèles sont modifiées et mettre à jour l’index de recherche en réponse.

Jetez un oeil à cette syntaxe pour la recherche en texte intégral, pour trouver n’importe quel Review avec le mot Llew dedans :

Review::search('Llew')->get();
Review::search('Llew')->paginate(20);
Review::search('Llew')->where('account_id', 2)->get();

Tout cela avec très peu de configuration. C’est une belle chose.

Installation de Scout

Tout d’abord, insérez le package (une fois qu’il est en ligne et sur une application Laravel 5.3):

composer require laravel/scout

Ensuite, ajoutez le fournisseur de services Scout (Laravel\Scout\ScoutServiceProvider::class) au providers section de config/app.php.

Nous voudrons mettre en place notre configuration Scout. Courir php artisan vendor:publish et collez vos identifiants Algolia dans config/scout.php.

Enfin, en supposant que vous utilisez Algolia, installez le SDK Algolia :

composer require algolia/algoliasearch-client-php

Marquage de votre modèle pour l’indexation

Maintenant, allez à votre modèle (nous utiliserons Review, pour une critique de livre, pour cet exemple). Importez le Laravel\Scout\Searchable trait. Vous pouvez définir quelles propriétés peuvent être recherchées à l’aide de la toSearchableArray() méthode (par défaut, la mise en miroir toArray()), et définissez le nom de l’index du modèle à l’aide de la searchableAs() méthode (il s’agit par défaut du nom de la table).

Une fois que nous avons fait cela, vous pouvez aller consulter votre page d’index Algolia sur leur site Web; lorsque vous ajoutez, mettez à jour ou supprimez Review enregistrements, vous verrez la mise à jour de votre index Algolia. Juste comme ça.

Recherche dans votre index

Nous avons déjà jeté un coup d’œil à cela, mais voici une actualisation de la façon de rechercher :

// Get all records from the Review that match the term "Llew"
Review::search('Llew')->get();

// Get all records from the Review that match the term "Llew",
// limited to 20 per page and reading the ?page query parameter,
// just like Eloquent pagination
Review::search('Llew')->paginate(20);

// Get all records from the Review that match the term "Llew"
// and have an account_id field set to 2
Review::search('Llew')->where('account_id', 2)->get();

Qu’est-ce qui ressort de ces recherches ? Une collection de modèles éloquents, réhydratés à partir de votre base de données. Les identifiants sont stockés dans Algolia, qui renvoie une liste d’identifiants correspondants, puis Scout extrait les enregistrements de la base de données pour ceux-ci et les renvoie sous forme d’objets Eloquent.

Vous n’avez pas un accès complet à la complexité de SQL where commandes, mais il gère un cadre de base solide pour les vérifications de comparaison comme vous pouvez le voir dans les exemples de code ci-dessus.

Files d’attente

Vous pouvez probablement deviner que nous envoyons maintenant des requêtes HTTP à Algolia à chaque requête qui modifie des enregistrements de base de données. Cela peut ralentir les choses très rapidement, vous pouvez donc vous retrouver à vouloir mettre ces opérations en file d’attente, ce qui, heureusement, est simple.

Dans config/scout.phpensemble queue pour true afin que ces mises à jour soient définies pour être indexées de manière asynchrone. Nous examinons maintenant la “cohérence éventuelle” ; vos enregistrements de base de données recevront les mises à jour immédiatement, et les mises à jour de vos index de recherche seront mises en file d’attente et mises à jour aussi rapidement que votre file d’attente le permet.

Cas spéciaux

Couvrons quelques cas particuliers.

Effectuer des opérations sans indexation

Que faire si vous souhaitez effectuer un ensemble d’opérations et éviter de déclencher l’indexation en réponse ? Enveloppez-les simplement dans withoutSyncingToSearch() méthode sur votre modèle :

Review::withoutSyncingToSearch(function () {
    // make a bunch of reviews, e.g.
    factory(Review::class, 10)->create();
});

Déclencher manuellement l’indexation via le code

Disons que vous êtes maintenant prêt à effectuer les index, maintenant qu’une opération en bloc a été effectuée avec succès. Comment?

Ajoutez simplement searchable() à la fin de toute requête Eloquent et il indexera tous les enregistrements trouvés dans cette requête.

Review::all()->searchable();

Vous pouvez également choisir de limiter la requête à ceux que vous souhaitez indexer, mais il convient de noter que l’indexation insérera de nouveaux enregistrements et mettra à jour les anciens enregistrements, il n’est donc pas mauvais de la laisser s’exécuter sur certains enregistrements qui peuvent déjà être indexés.

Cela fonctionnera également sur une relation :

$user->reviews()->searchable();

Vous pouvez également désindexer tous les enregistrements avec le même type de chaînage de requêtes, mais en utilisant simplement unsearchable() plutôt:

Review::where('sucky', true)->unsearchable();

Déclencher manuellement l’indexation via CLI

Il y a une commande Artisan pour ça.™

php artisan scout:import App\\Review

Cela va écraser tout le Review modèles et indexez-les tous.

Conclusion

C’est ça! Avec presque aucun travail, vous avez maintenant une recherche complète en texte intégral en cours d’exécution sur vos modèles Eloquent.