Heim >Backend-Entwicklung >PHP-Tutorial >Pinq - Fragen Sie Ihre Datensätze an - Facetten -Suche
Wir werden nicht den vollen Aspekt der Facett -Suche in dieser Serie abdecken. Interessierte Parteien können auf relevante Artikel verweisen, die auf SitePoint und anderen Internetveröffentlichungen veröffentlicht wurden.
Eine typische facettierte Suche funktioniert wie diese in einer Website:
Ein Benutzer stellt ein Schlüsselwort oder einige Schlüsselwörter zur Suche nach. Zum Beispiel „Router“, um nach Produkten zu suchen, die „Router“ in der Beschreibung, in der Schlüsselwort, in der Kategorie, in den Tags usw. enthalten.
Leider ist die Facette-Suche noch keine integrierte Funktion von MySQL. Was können wir tun, wenn wir MySQL verwenden, aber unseren Benutzern auch eine solche Funktion bieten möchten?
Mit Pinq werden wir sehen, dass es einen ebenso leistungsstarken und einfachen Ansatz gibt, um dies zu erreichen, als wenn wir andere DB -Motoren verwenden - zumindest in gewisser Weise.
Teil 1 Demo
erweiternIn diesem Artikel werden wir die Demo erweitern, die wir in Teil 1 gezeigt haben, und einige wichtige, facettierte Suchfunktionen hinzufügen.
Beginnen wir mit index.php, indem wir die folgenden Zeilen hinzufügen:
Wir haben gerade zwei weitere Routen in unserer Demo -Anwendung (mit Silex) erstellt.
<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>
Die erste Route besteht darin, uns auf die Seite zu bringen, die alle Datensätze zeigt, die unserem ersten Suchverhalten entsprechen, d. H. Durch die Suche eines Schlüsselworts. Um die Demo einfach zu halten, wählen wir alle Bücher aus der Tabelle book_book aus. Außerdem werden die Ergebnisse und facettierte Links für die weitere Navigation angezeigt.
Die zweite Route bringt uns zu einer anderen Seite, die die Datensätze zeigt, die weitere Facetten -Suchkriterien in dem im obigen Schritt erstellten Ergebnis -Set entsprechen. Es werden auch die facettierten Suchlinks angezeigt.
In einer realen Implementierung wird nach dem Klicken eines facettierten Links jede facettierte Filterung auf der Ergebnisseite angepasst, um die statistischen Informationen des Ergebnisdatensatzes widerzuspiegeln. Auf diese Weise kann der Benutzer "Add-On" -Sichtweite anwenden und zuerst „Marke“ hinzufügen und dann „Preisspanne“ usw.
Aber in dieser einfachen Demo werden wir diesen Ansatz überspringen, alle facettierten Suche und die Links werden nur die Informationen zum Originaldatensatz widerspiegeln. Dies ist die erste Einschränkung und der erste Bereich für Verbesserungen in unserer Demo.
Wie wir aus dem obigen Code sehen, befinden sich die realen Funktionen in einer anderen Datei namens Pinqdemo.php. Sehen wir uns den relevanten Code an, der die facettierte Suchfunktion bietet.
Erstens erstellen wir eine Klasse, um eine Facette darzustellen. Im Allgemeinen sollte eine Facette einige Eigenschaften haben:
Die Gruppierung ist der kritischste Teil einer Facette. Alle aggregierenden Informationen, die eine Facette möglicherweise zurückgeben könnte, hängt von den "Gruppierungskriterien" ab. Normalerweise sind „Vollstring“, „Teilzeichenfolge“ und „Wertebereich“ die am häufigsten verwendeten.
<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>
In dieser Klasse besteht die Schlüsselfunktion darin, das facettierte Ergebnissatz basierend auf den Daten und den Facettenschlüsseleigenschaften zurückzugeben. Wir haben festgestellt, dass es für verschiedene Tastenarten verschiedene Möglichkeiten gibt, die Daten zu gruppieren. Im obigen Punkt haben wir gezeigt, wie der Code aussehen wird, wenn wir die Daten nach einem Wertebereich in einem von $ Range angegebenen Schritt gruppieren.
<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>
In der Funktion getfacet () machen wir die folgenden Schritte aus:
Meistens werden Facetten als Link angezeigt und bringen uns zu einem gefilterten Datensatz.
Wir haben bereits eine Route erstellt ('Demo2/facet/{key}/{value}'), um die facettierten Suchergebnisse und die Facettenlinks anzuzeigen.
Die Route nimmt zwei Parameter vor, die den Schlüssel widerspiegeln, auf dem wir facetten, und den Wert dieses Schlüssels. Die Test3 -Funktion, die schließlich von dieser Route aufgerufen wird
<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>Abhängig vom Schlüssel wenden wir im Grunde die Filterung (die anonyme Funktion in der Klausel) an, die dem in übergebenen Wert entspricht, und erhalten die weiteren gescreenten Daten. Wir können auch die Reihenfolge der facettierten Daten angeben.
Schließlich zeigen wir die Daten (zusammen mit den Facetten) in einer Vorlage an. Diese Route macht die gleiche Vorlage wie die, die auf der Route 'Demo2' verwendet wird.
Schauen wir uns als nächstes die Vorlage an und sehen Sie, wie die Facettenlinks angezeigt werden. Ich verwende Bootstrap, damit die hier verwendeten CSS -Komponenten ziemlich vertraut sein sollten:
<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>Wir müssen uns daran erinnern, dass die von unserer App generierte Facette ein verschachteltes Array ist. In der ersten Schicht ist es eine Reihe aller Facetten, und in unserem Fall haben wir insgesamt 3 (für Autor, Titel, Autor).
Für jede Facette handelt es sich um ein "Schlüsselwert" gepaartes Array, damit wir auf traditionelle Weise iterieren können.
Bitte beachten Sie, wie wir die URIs der Links erstellen. Wir haben sowohl den Schlüssel (K) als auch den Inner Loops -Schlüssel (Vv.Key) der Außenschleife als Parameter in der Route ('Demo2/facet/{Key}/{value}') verwendet. Die Anzahl der Schlüssel (VV.Count) wird verwendet, um das Display in der Vorlage (als Bootstrap -Abzeichen) zu verbessern.
Die Vorlage wird wie unten gezeigt gerendert:
In Ordnung, bisher haben wir es geschafft, eine facettierte Suchfunktion in unserer Web -App nachzuahmen!
Bevor wir diese Serie abschließen, werden wir uns diese Demo abschließen und sehen, was getan werden kann, um sie zu verbessern und was die Grenzen sind.
Wir müssen in Betracht ziehen, "Add-On" -Kriterien zur Suche nach Funktionen zu geben. Unsere aktuelle Implementierung begrenzt die Facettensuche, die nur auf das Original angewendet wird, anstatt der gescreenten Daten. Dies ist die wichtigste Verbesserung, die ich mir vorstellen kann.
Einschränkungen
Wir reichen jedes Mal Daten vom MySQL -Server ab.
Diese App verwendet Silex als Framework. Für jedes Einzeleingangs-Framework wie Silex, Symfony, Laravel, sein Index.php (oder app.php) wird jedes Mal aufgerufen, wenn eine Route analysiert und die Funktion eines Controllers aufgerufen wird.
Wenn wir den Code in unserem Index.php betrachten, werden wir feststellen, dass dies auch die folgende Codezeile bedeutet:
<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>wird jedes Mal aufgerufen, wenn eine Seite in der App angezeigt wird, was bedeutet, dass die folgenden Zeilen jedes Mal ausgeführt werden:
<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>Wird es besser sein, wenn wir vermeiden, ein Framework zu verwenden? Nun, abgesehen von der Tatsache, dass es nicht wirklich eine sehr gute Idee ist, eine App ohne Framework zu entwickeln, stehen wir immer noch vor dem gleichen Problem: Daten (und Status) sind von einem HTTP -Anruf zum anderen nicht bestehen. Dies ist das grundlegende Merkmal von HTTP. Dies sollte durch die Verwendung eines Caching -Motors vermieden werden.
wir speichern einige SQL -Anweisungen, die auf der Serverseite ausgeführt werden, wenn wir die Facetten erstellen. Anstatt 1 Abfrage auszuwählen und 3 verschiedene Gruppen durch Abfragen mit derselben Where -Anweisung auszuwählen, geben wir nur eine Auswahl von Abfrage mit der WHERE -Anweisung aus und verwenden PINQ, um die Aggregationsinformationen bereitzustellen.
Schlussfolgerung
Der Autor von Pinq arbeitet jetzt an der nächsten Major -Versionsveröffentlichung (Version 3). Ich hoffe, es kann mächtiger werden.
Fühlen Sie sich frei, Ihre Kommentare und Gedanken unten zu hinterlassen!
häufig gestellte Fragen (FAQs) zu PINQ und Facetted Search
Wie stellt PINQ die Genauigkeit der Suchergebnisse sicher? Abfragesprache, die Daten genau basierend auf mehreren Kriterien filtern und sortieren kann. Dies ermöglicht es, präzise und relevante Suchergebnisse bereitzustellen.
Das obige ist der detaillierte Inhalt vonPinq - Fragen Sie Ihre Datensätze an - Facetten -Suche. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!