Maison >développement back-end >tutoriel php >PINQ - REQUIREZ VOTRE ensemble de données - Recherche à facettes
Dans la partie 1, nous avons brièvement couvert l'installation et la syntaxe de base de PINQ, un port PHP LINQ. Dans cet article, nous verrons comment utiliser PINQ pour imiter une fonction de recherche à facettes avec mysql.
Nous n'allons pas couvrir le plein aspect de la recherche à facettes dans cette série. Les parties intéressées peuvent se référer aux articles pertinents publiés sur SitePoint et d'autres publications Internet.
Une recherche à facettes typique fonctionne comme celle-ci dans un site Web:
La recherche à facettes est si populaire et puissante et vous pouvez en faire l'expérience dans presque tous les site de commerce électronique.
Malheureusement, la recherche à facettes n'est pas encore une fonctionnalité intégrée fournie par MySQL. Que pouvons-nous faire si nous utilisons MySQL mais que nous voulons également fournir à nos utilisateurs une telle fonctionnalité?
Avec PINQ, nous verrons qu'il existe une approche tout aussi puissante et simple pour y parvenir comme lorsque nous utilisons d'autres moteurs DB - du moins d'une certaine manière.
Remarque: tout le code de cette partie et la démonstration de la partie 1 peuvent être trouvés dans le dépôt.
Dans cet article, nous prolongerons la démo que nous avons montrée dans la partie 1 et ajouterons certaines fonctionnalités de recherche à facettes essentielles.
Commençons par index.php en ajoutant les quelques lignes suivantes:
<span>$app->get('demo2', function () use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test2 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test2->test2($app, $demo->test1($app)); </span><span>} </span><span>); </span> <span>$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test3 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test3->test3($app, $demo->test1($app), $key, $value); </span><span>} </span><span>);</span>
Nous venons de créer deux autres itinéraires dans notre application de démonstration (en utilisant Silex).
La première route consiste à nous amener à la page affichant tous les enregistrements qui correspondent à notre premier comportement de recherche, c'est-à-dire la recherche en fournissant un mot-clé. Pour garder la démo simple, nous sélectionnons tous les livres dans l'exemple de table book_book. Il affichera également l'ensemble de résultats et les liens à facettes pour une navigation supplémentaire.
Le deuxième itinéraire nous amène à une autre page montrant les enregistrements correspondant aux autres critères de recherche de facettes dans l'ensemble de résultats produit à l'étape ci-dessus. Il affichera également les liens de recherche à facettes.
Dans une implémentation du monde réel, une fois un lien à facettes cliqué, tout filtrage à facettes dans la page de résultats sera ajusté pour refléter les informations statistiques de l'ensemble de données de résultat. Ce faisant, l'utilisateur peut appliquer des dépistages «complémentaires», en ajoutant «marque» d'abord puis «gamme de prix», etc.
Mais dans cette démo simple, nous sauterons cette approche, toutes les recherches à facettes et les liens ne refléteront que les informations sur l'ensemble de données d'origine. Il s'agit de la première restriction et du premier domaine d'amélioration de notre démo.
Comme nous le voyons dans le code ci-dessus, les fonctions réelles résident dans un autre fichier appelé pinqdemo.php. Voyons le code pertinent qui fournit la fonction de recherche à facettes.
Tout d'abord, nous créons une classe pour représenter une facette. Généralement, une facette doit avoir quelques propriétés:
Le regroupement est la partie la plus critique d'une facette. Toutes les informations d'agrégation qu'une facette pourrait éventuellement retourner dépend des critères de «regroupement». Normalement, la «chaîne complète», la «chaîne partielle» et la «plage de valeur» sont les plus couramment utilisées.
<span>$app->get('demo2', function () use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test2 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test2->test2($app, $demo->test1($app)); </span><span>} </span><span>); </span> <span>$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test3 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test3->test3($app, $demo->test1($app), $key, $value); </span><span>} </span><span>);</span>
Dans cette classe, la fonction clé consiste à renvoyer l'ensemble de résultats à facettes en fonction des données et des propriétés de clé de facette. Nous avons remarqué que pour différents types de clés, il existe différentes façons de regrouper les données. Dans ce qui précède, nous avons montré à quoi ressemblera le code si nous regroupons les données par une plage de valeur dans une étape spécifiée par $ plage.
<span>namespace classFacet </span><span>{ </span> <span>use Pinq<span>\ITraversable</span>, </span> Pinq\Traversable<span>; </span> <span>class Facet </span> <span>{ </span> <span>public $data; // Original data </span> <span>public $key; // the field to be grouped on </span> <span>public $type; // F: full string; S: start of a string; R: range; </span> <span>public $range; // Only valid if $type is not F </span> <span>... </span> <span>public function getFacet() </span> <span>{ </span> <span>$filter = ''; </span> <span>if ($this->type == 'F') // Full string </span> <span>{ </span> <span>... </span> <span>} </span> <span>elseif ($this->type == "S") //Start of string </span> <span>{ </span> <span>... </span> <span>} </span> <span>elseif ($this->type == "R") // A value range </span> <span>{ </span> <span>$filter = $this->data </span> <span>->groupBy(function($row) </span> <span>{ </span> <span>return floor($row[$this->key] / $this->range) * $this->range; </span> <span>}) </span> <span>->select(function (ITraversable $data) </span> <span>{ </span> <span>return ['key' => $data->last()[$this->key], 'count' => $data->count()]; </span> <span>}); </span> <span>} </span> <span>return $filter; </span> <span>} </span> <span>} </span><span>}</span>
Dans la fonction getfacet (), nous effectuons les étapes suivantes:
La plupart du temps, les facettes seront affichées sous forme de lien et nous amèneront à un ensemble de données filtrées.
Nous avons déjà créé une route ('Demo2 / Facet / {Key} / {Value}') pour afficher les résultats de recherche à facettes et les liens de facette.
L'itinéraire prend deux paramètres, reflétant la clé sur laquelle nous facet et la valeur de cette clé. La fonction TEST3 qui finit par être invoquée à partir de cette route est extraite ci-dessous:
<span>$app->get('demo2', function () use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test2 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test2->test2($app, $demo->test1($app)); </span><span>} </span><span>); </span> <span>$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test3 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test3->test3($app, $demo->test1($app), $key, $value); </span><span>} </span><span>);</span>
Fondamentalement, en fonction de la clé, nous appliquons le filtrage (la fonction anonyme dans la clause) correspondant à la valeur transmise et obtenez les données supplémentaires. Nous pouvons également spécifier l'ordre des données à facettes.
Enfin, nous affichons les données (avec les facettes) dans un modèle. Cette route rend le même modèle que celui qui est utilisé par la route 'Demo2').
Ensuite, jetons un coup d'œil au modèle et voyons comment les liens de facette sont affichés. J'utilise Bootstrap pour que les composants CSS utilisés ici soient assez familiers:
<span>namespace classFacet </span><span>{ </span> <span>use Pinq<span>\ITraversable</span>, </span> Pinq\Traversable<span>; </span> <span>class Facet </span> <span>{ </span> <span>public $data; // Original data </span> <span>public $key; // the field to be grouped on </span> <span>public $type; // F: full string; S: start of a string; R: range; </span> <span>public $range; // Only valid if $type is not F </span> <span>... </span> <span>public function getFacet() </span> <span>{ </span> <span>$filter = ''; </span> <span>if ($this->type == 'F') // Full string </span> <span>{ </span> <span>... </span> <span>} </span> <span>elseif ($this->type == "S") //Start of string </span> <span>{ </span> <span>... </span> <span>} </span> <span>elseif ($this->type == "R") // A value range </span> <span>{ </span> <span>$filter = $this->data </span> <span>->groupBy(function($row) </span> <span>{ </span> <span>return floor($row[$this->key] / $this->range) * $this->range; </span> <span>}) </span> <span>->select(function (ITraversable $data) </span> <span>{ </span> <span>return ['key' => $data->last()[$this->key], 'count' => $data->count()]; </span> <span>}); </span> <span>} </span> <span>return $filter; </span> <span>} </span> <span>} </span><span>}</span>
Nous devons nous rappeler que la facette générée par notre application est un réseau imbriqué. Dans la première couche, il s'agit d'un tableau de toutes les facettes, et dans notre cas, nous avons un total de 3 (pour auteur, titre, auteur, respectivement).
Pour chaque facette, il s'agit d'un tableau apparié «Valeur clé» afin que nous puissions itérer de manière traditionnelle.
Veuillez noter comment nous construisons les URI des liens. Nous avons utilisé à la fois la clé de la boucle extérieure (k) et la clé de boucles internes (vv.key) pour être les paramètres de la route ('Demo2 / Facet / {key} / {value}'). Le nombre de la clé (Vv.Count) est utilisé pour retoucher l'affichage dans le modèle (en tant que badge bootstrap).
Le modèle sera rendu comme indiqué ci-dessous:
(le premier montre la page d'entrée initiale et le second affiche un résultat à facettes avec un prix entre 0 $ et 10 $ et commandé par l'auteur)
Très bien, jusqu'à présent, nous avons réussi à imiter une fonction de recherche à facettes dans notre application Web!
Avant de conclure cette série, nous allons jeter un coup d'œil à cette démo et voir ce qui peut être fait pour l'améliorer et quelles sont les limites.
Dans l'ensemble, il s'agit d'une démo assez rudimentaire. Nous venons de parcourir la syntaxe et les concepts de base et les avons forgés dans un exemple de canette. Comme nous l'avons vu plus tôt, quelques zones peuvent être améliorées pour la rendre plus flexible.
Nous devons envisager de fournir une capacité de recherche de critères «complémentaire». Notre implémentation actuelle limite la recherche de facettes à appliquer uniquement sur l'original, au lieu des données criblées. C'est l'amélioration la plus importante à laquelle je peux penser.
La recherche à facettes implémentée ici a une limitation profonde (et probablement vrai pour les autres implémentations de recherche à facettes):
Nous récupérons les données du serveur MySQL à chaque fois.
Cette application utilise Silex comme cadre. Pour tout cadre d'entrée unique comme Silex, Symfony, Laravel, son index.php (ou app.php) est appelé chaque fois qu'un itinéraire doit être analysé et la fonction d'un contrôleur doit être invoquée.
En regardant le code dans notre index.php, nous verrons que cela signifie également la ligne de code ci-dessous:
<span>$app->get('demo2', function () use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test2 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test2->test2($app, $demo->test1($app)); </span><span>} </span><span>); </span> <span>$app->get('demo2/facet/{key}/{value}', function ($key, $value) use ($app) </span><span>{ </span> <span>global $demo; </span> <span>$test3 = new pinqDemo<span>\Demo</span>($app); </span> <span>return $test3->test3($app, $demo->test1($app), $key, $value); </span><span>} </span><span>);</span>
s'appelle chaque fois qu'une page de l'application s'affiche, ce qui signifie alors que les lignes suivantes sont exécutées à chaque fois:
<span>namespace classFacet </span><span>{ </span> <span>use Pinq<span>\ITraversable</span>, </span> Pinq\Traversable<span>; </span> <span>class Facet </span> <span>{ </span> <span>public $data; // Original data </span> <span>public $key; // the field to be grouped on </span> <span>public $type; // F: full string; S: start of a string; R: range; </span> <span>public $range; // Only valid if $type is not F </span> <span>... </span> <span>public function getFacet() </span> <span>{ </span> <span>$filter = ''; </span> <span>if ($this->type == 'F') // Full string </span> <span>{ </span> <span>... </span> <span>} </span> <span>elseif ($this->type == "S") //Start of string </span> <span>{ </span> <span>... </span> <span>} </span> <span>elseif ($this->type == "R") // A value range </span> <span>{ </span> <span>$filter = $this->data </span> <span>->groupBy(function($row) </span> <span>{ </span> <span>return floor($row[$this->key] / $this->range) * $this->range; </span> <span>}) </span> <span>->select(function (ITraversable $data) </span> <span>{ </span> <span>return ['key' => $data->last()[$this->key], 'count' => $data->count()]; </span> <span>}); </span> <span>} </span> <span>return $filter; </span> <span>} </span> <span>} </span><span>}</span>
sera-t-il mieux si nous évitons d'utiliser un cadre? Eh bien, en plus du fait que ce n'est pas vraiment une très bonne idée de développer une application sans cadre, nous sommes toujours confrontés au même problème: les données (et le statut) ne sont pas persistants d'un appel HTTP à un autre. C'est la caractéristique fondamentale de HTTP. Cela doit être évité avec l'utilisation d'un moteur de mise en cache.
Nous enregistrons certaines instructions SQL exécutées du côté du serveur lorsque nous construisons les facettes. Au lieu de passer 1 requête de sélection et 3 requêtes de groupe différentes par la même instruction, nous émettant simplement une requête sélectionnée avec l'instruction WHERE et utilisons PINQ pour fournir les informations d'agrégation.
Dans cette partie, nous avons réussi à imiter une capacité de recherche de facettes pour notre site de collecte de livres. Comme je l'ai dit, il s'agit simplement d'une démo à canette et a beaucoup d'amélioration et certaines limitations par défaut. Faites-nous savoir si vous construisez sur cet exemple et pouvez nous montrer des cas d'utilisation plus avancés!
L'auteur de PINQ travaille maintenant sur la prochaine version de version principale (version 3). J'espère que cela peut devenir plus puissant.
N'hésitez pas à laisser vos commentaires et vos pensées ci-dessous!
PINQ est une bibliothèque PHP qui fournit un langage de requête unique, intuitif et puissant pour manipuler des tableaux et d'autres ensembles de données. Il est conçu pour simplifier le processus de requête et de manipulation des données. En ce qui concerne la recherche à facettes, PINQ peut être utilisé pour créer des requêtes complexes qui peuvent filtrer et trier les données en fonction de plusieurs critères, qui est le concept principal de la recherche à facettes.
L'approche de Pinq de la recherche à facettes est unique car elle utilise un langage de requête basé sur PHP, qui est un langage de programmation largement utilisé. Cela facilite les développeurs qui connaissent déjà PHP pour implémenter la recherche facettée. De plus, le langage de requête de Pinq est conçu pour être intuitif et facile à utiliser, ce qui peut simplifier le processus de création de requêtes complexes.
PINQ n'est pas limité à MySQL. Il peut être utilisé avec n'importe quel ensemble de données, y compris les tableaux et autres bases de données. Cette flexibilité fait de PINQ un outil polyvalent pour les développeurs qui ont besoin de travailler avec différents types de données.
PINQ est conçu pour gérer efficacement de grands ensembles de données. Il le fait en utilisant une stratégie d'évaluation paresseuse, ce qui signifie qu'il ne traite que les données lorsqu'elle est réellement nécessaire. Cela peut améliorer considérablement les performances lorsque vous travaillez avec de grands ensembles de données.
L'utilisation de PINQ pour la recherche à facettes présente plusieurs avantages. Premièrement, il simplifie le processus de création de requêtes complexes, ce qui peut faire gagner du temps et des efforts pour les développeurs. Deuxièmement, il fournit un langage de requête puissant et flexible qui peut gérer un large éventail de types de données et de structures. Enfin, il est basé sur PHP, qui est un langage de programmation largement utilisé, ce qui facilite l'apprentissage et l'utilisation des développeurs. 🎜> PINQ est conçu pour être intuitif et facile à utiliser, ce qui le rend adapté aux débutants et aux développeurs expérimentés. Cependant, une certaine connaissance des langages PHP et de requête est bénéfique lors de l'utilisation de PINQ.
PINQ assure la précision des résultats de recherche en utilisant un puissant et flexible Interroger le langage qui peut filtrer et trier avec précision les données en fonction de plusieurs critères. Cela lui permet de fournir des résultats de recherche précis et pertinents.
Oui, PINQ peut être utilisé pour une recherche en temps réel. Sa gestion efficace des grands ensembles de données et sa capacité à créer des requêtes complexes le rendent adapté aux applications de recherche en temps réel.
PINQ Stands D'autres bibliothèques PHP pour la recherche à facettes en raison de son langage de requête unique, intuitif et puissant. Il offre également une flexibilité en termes de types de données qu'il peut gérer, et sa manipulation efficace de grands ensembles de données en fait un choix fort pour les développeurs.
Oui, PINQ est une bibliothèque open source, ce qui signifie que les développeurs peuvent le personnaliser en fonction de leurs besoins spécifiques. Cette flexibilité est un autre avantage de l'utilisation de PINQ pour la recherche à facettes.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!