Erstellen Sie herausragende React-Sucherlebnisse im Handumdrehen
15.11.2019: In der Originalversion dieses Blogposts fehlten im Programmiercode geschweifte Klammern. Diese haben wir ergänzt. Außerdem wurde der Fluss korrigiert, um Laufzeitfehler zu vermeiden. |
Die Entwicklung von Sucherlebnissen ist kein Zuckerschlecken. Auf den ersten Blick erscheint alles einfach: Sie erstellen eine Suchleiste, füllen die Datenbank mit Daten und verwenden Benutzereingaben, um die Datenbank abzufragen. Bei der Datenmodellierung, der zugrunde liegenden Logik und selbstverständlich dem Gesamtdesign und der User Experience müssen jedoch viele Punkte beachtet werden.
Wir zeigen Ihnen Schritt für Schritt, wie Sie mit der Open Source-Bibliothek Search UI von Elastic herausragende, React-basierte Sucherlebnisse erstellen können. In etwa 30 Minuten erfahren Sie, wie Sie beliebige Anwendungen mit einer Suchfunktion ausstatten können.
Aber zunächst fragen wir uns, warum Suchfunktionen so schwierig sind.
Suchen ist schwierig
Vor einigen Wochen machte ein hervorragender Artikel mit dem Titel Falsehoods Programmers Believe About Search (Falsche Ansichten von Programmierern über Suchfunktionen) die Runde. Dieser Artikel enthält eine ausführliche Liste mit falschen Annahmen, unter denen Suchfunktionen entwickelt werden.
Einige Beispiele für diese falschen Annahmen:
- „Wenn ein Kunde weiß, wonach er sucht, dann wird er auf die erwartete Art danach suchen.“
- „Es ist möglich, einen Abfrage-Parser zu schreiben, der jede Suchanfrage erfolgreich analysiert.“
- „Nach der Einrichtung funktioniert die Suche auch eine Woche später noch genau gleich.“
- „Synonyme sind einfach.“
- … Und viele weitere Perlen – lesen Sie den Artikel unbedingt!
Der Autor kommt zum Schluss, dass Suchfunktionen kompliziert sind und nicht nur hinter den Kulissen stattfinden. Sie müssen sich Gedanken darüber machen, wie Sie den Zustand verwalten und müssen Komponenten für Filter, Facets, Sortierung, Paginierung, Synonyme, Sprachverarbeitung und vieles, vieles ... vieles mehr erstellen. Aber, kurz gesagt:
Eine gute Suchfunktion besteht aus zwei komplexen Komponenten: (1) der Suchmaschine, die APIs für Suchfunktionen bereitstellt, und (2) der Suchbibliothek, die das Sucherlebnis grafisch darstellt.
Als Suchmaschine werden wir Elastic App Search verwenden.
Für das Sucherlebnis präsentieren wir eine OS-Suchbibliothek: Search UI.
Das Ergebnis wird im Anschluss so aussehen:
Suchmaschine: Elastic App Search
App Search ist entweder als zahlungspflichtiger, verwalteter Dienst verfügbar oder als selbstverwaltete Distribution. Für dieses Tutorial verwenden wir den verwalteten Dienst, aber Ihr Team kann Search UI und App Search mit einer einfachen Lizenz kostenlos einsetzen, wenn Sie die Lösung selbst hosten.
Der Plan: Wir möchten Dokumente mit den besten Videospielen aller Zeiten in eine Suchmaschine indexieren und anschließend ein Sucherlebnis gestalten und optimieren, um die Dokumente zu durchsuchen.
Registrieren Sie sich zunächst für eine 14-tägige Testversion - dazu brauchen Sie keine Kreditkarte.
Erstellen Sie eine Engine. Sie haben die Wahl zwischen 13 verschiedenen Sprachen.
Wir geben ihr den Namen video-games
und verwenden die Sprache Englisch.
Laden Sie den Datensatz mit den besten Videospielen herunter und laden Sie ihn anschließend mit dem Importer in App Search hoch.
Klicken Sie anschließend in die Engine und wählen Sie die Registerkarte Credentials aus.
Erstellen Sie einen neuen Public Search Key mit Limited Engine Access für die Engine video-games
.
Rufen Sie den neuen Public Search Key und Ihren Host Identifier ab.
Auch wenn es noch nicht so aussieht, haben wir bereits eine voll funktionsfähige Suchmaschine, die unsere Videospieldaten mit einer leistungsstarken Such-API durchsuchen kann.
Was wir bisher erledigt haben:
- Eine Suchmaschine erstellt
- Dokumente ingestiert
- Ein Standardschema erstellt
- Umfangsgebundene und nicht sicherheitsrelevante Anmeldeinformationen abgerufen, die wir an den Browser weitergeben können
Damit ist App Search vorerst versorgt.
Anschließend werden wir unser Sucherlebnis mit Search UI erstellen.
Suchbibliothek: Search UI
Wir werden create-react-app als Hilfsgerüst verwenden, um eine React-App zu erstellen:
npm install -g create-react-app create-react-app video-game-search --use-npm cd video-game-search
Auf dieser Basis installieren wir Search UI und den App Search-Connector:
npm install --save @elastic/react-search-ui @elastic/search-ui-app-search-connector
Anschließend starten wir die App im Entwicklungsmodus:
npm start
Öffnen Sie src/App.js
in Ihrem bevorzugten Texteditor.
Wir beginnen mit dem folgenden Codebaustein und gehen anschließend in die Details.
Achten Sie auf die Kommentare!
// Schritt 1, import-Anweisungen import React from "react"; import AppSearchAPIConnector from "@elastic/search-ui-app-search-connector"; import { SearchProvider, Results, SearchBox } from "@elastic/react-search-ui"; import { Layout } from "@elastic/react-search-ui-views"; import "@elastic/react-search-ui-views/lib/styles/styles.css"; // Schritt 2, der Connector const connector = new AppSearchAPIConnector({ searchKey: "[YOUR_SEARCH_KEY]", engineName: "video-games", hostIdentifier: "[YOUR_HOST_IDENTIFIER]" }); // Schritt 3: Konfigurationsoptionen const configurationOptions = { apiConnector: connector // Diesen Teil füllen wir gemeinsam aus. // Schritt 4, SearchProvider: der letzte Schliff // Diesen Teil füllen wir gemeinsam aus.
Schritt 1: import-Anweisungen
Wir müssen unsere Search UI-Abhängigkeiten und React importieren.
Die Kernkomponenten, der Connector und die View-Komponenten sind in drei verschiedenen Paketen enthalten:
@elastic/search-ui-app-search-connector
@elastic/react-search-ui
@elastic/react-search-ui-views
Wir werden uns im weiteren Verlauf näher mit diesen Paketen befassen.
import React from "react"; import AppSearchAPIConnector from "@elastic/search-ui-app-search-connector"; import { SearchProvider, Results, SearchBox } from "@elastic/react-search-ui"; import { Layout } from "@elastic/react-search-ui-views";
Außerdem importieren wir ein Standard-Stylesheet für dieses Projekt, um ihm ein ansprechendes Erscheinungsbild zu verleihen, ohne eine Zeile CSS zu schreiben:
import "@elastic/react-search-ui-views/lib/styles/styles.css";
Schritt 2: Der Connector
Wir haben unseren Public Search Key und unseren Host Identifier aus App Search.
Jetzt werden wir sie einsetzen!
Das connector-Objekt in Search UI verwendet die Anmeldeinformationen, um sich mit App Search und Power Search zu verbinden:
const connector = new AppSearchAPIConnector({ searchKey: "[YOUR_SEARCH_KEY]", engineName: "video-games", hostIdentifier: "[YOUR_HOST_IDENTIFIER]" });
Search UI kann mit beliebigen Such-APIs eingesetzt werden. Der Connector sorgt dafür, dass die Such-API ohne ausführliche Konfiguration problemlos funktioniert.
Schritt 3: configurationOptions
Lassen Sie uns einen Moment nachdenken, bevor wir uns die configurationOptions
genauer ansehen.
Wir haben einen Datensatz in unsere Suchmaschine importiert. Aber worum geht es in diesen Daten?
Je mehr wir über unsere Daten wissen, desto besser können wir sie in unserer Suche darstellen. Daraus ergibt sich die Konfiguration des Sucherlebnisses.
Sehen Sie sich das ein Objekt in unserem Datensatz an, das besonders heraussticht:
{ "id":"final-fantasy-vii-ps-1997", "name":"Final Fantasy VII", "year":1997, "platform":"PS", "genre":"Role-Playing", "publisher":"Sony Computer Entertainment", "global_sales":9.72, "critic_score":92, "user_score":9, "developer":"SquareSoft", "image_url":"https://r.hswstatic.com/w_907/gif/finalfantasyvii-MAIN.jpg" }
Es enthält verschiedene Textfelder wie name
, year
, platform
und so weiter, und einige Zahlenfelder wie critic_score
, global_sales
und user_score
.
Für ein robustes Sucherlebnis stellen wir uns die folgenden drei Schlüsselfragen:
- Wonach werden die meisten Benutzer suchen? Nach dem Namen des Videospiels.
- Was möchten die meisten Benutzer in ihrem Ergebnis sehen? Name, Genre, Publisher, Wertungen und Plattform des Videospiels.
- Auf welche Kriterien werden die meisten Benutzer Filter, Sortierungen und Facets anwenden? Auf Punktzahl, Genre, Publisher und Plattform.
Anschließend können wir diese Antworten in unsere configurationOptions
übersetzen:
const configurationOptions = { apiConnector: connector, searchQuery: { search_fields: { // 1. Suche nach dem Namen des Videospiels. name: {} }, // 2. Ergebnisse: Name, Genre, Publisher, Wertungen und Plattform. result_fields: { name: { // Ein Snippet legt fest, dass übereinstimmende Suchbegriffe in <em>-Tags eingeschlossen werden. snippet: { size: 75, // Snippet auf 75 Zeichen beschränken. fallback: true // Fallback auf ein Ergebnis mit Rohdaten. } }, genre: { snippet: { size: 50, fallback: true } }, publisher: { snippet: { size: 50, fallback: true } }, critic_score: { // Wertungen sind numerisch, daher verwenden wir kein Snippet. raw: {} }, user_score: { raw: {} }, platform: { snippet: { size: 50, fallback: true } }, image_url: { raw: {} } }, // 3. Facet nach Wertungen, Genre, Publisher und Plattform, um später Filter erstellen zu können. facets: { user_score: { type: "range", ranges: [ { from: 0, to: 5, name: "Not good" }, { from: 5, to: 7, name: "Not bad" }, { from: 7, to: 9, name: "Pretty good" }, { from: 9, to: 10, name: "Must play!" } ] }, critic_score: { type: "range", ranges: [ { from: 0, to: 50, name: "Not good" }, { from: 50, to: 70, name: "Not bad" }, { from: 70, to: 90, name: "Pretty good" }, { from: 90, to: 100, name: "Must play!" } ] }, genre: { type: "value", size: 100 }, publisher: { type: "value", size: 100 }, platform: { type: "value", size: 100 } } } };
Wir haben Search UI mit unserer Suchmaschine verbunden und mit Optionen festgelegt, wie wir unsere Daten durchsuchen, unsere Ergebnisse anzeigen und anschließend mit diesen Ergebnissen arbeiten möchten. Jetzt werden wir unsere bisherige Arbeit mit den dynamischen Frontend-Komponenten von Search UI verknüpfen.
Schritt 4: SearchProvider
Ein Objekt, um sie alle zu binden. Im SearchProvider
werden alle anderen Komponenten gebündelt.
Search UI stellt eine Layout
-Komponente bereit, mit der Sie ein typisches Suchlayout erstellen können. Diese Komponente kann ausführlich angepasst werden, was jedoch den Rahmen dieses Tutorials sprengen würde.
Wir werden zwei Dinge erledigen:
- Unsere
configurationOptions
an denSearchProvider
übergeben. - Einige Bausteine im
Layout
ablegen und zwei wichtige Komponenten hinzufügen:SearchBox
undResults
.
export default function App() { return ( <SearchProvider config={configurationOptions}> <div className="App"> <Layout header={<SearchBox />} // titleField ist das wichtigste Feld in einem Ergebnis: die Ergebnisüberschrift. bodyContent={<Results titleField="name" urlField="image_url" />} /> </div> </SearchProvider> ); }
Wir haben jetzt die Grundlagen am Frontend eingerichtet. Bevor wir mit der Ausführung beginnen können, müssen wir noch ein paar Details im Backend klären. Außerdem sollten wir am Relevanzmodell arbeiten, um die Suche auf die einzigartigen Anforderungen dieses Projekts abzustimmen.
Weiter zur App Search ...
Zurück ins Labor
App Search stellt leistungsstarke und moderne Suchmaschinenfunktionen bereit. Mit diesen Funktionen macht die ehemals mühselige Feinabstimmung viel mehr Spaß. Wir können mit wenigen Klicks differenzierte Relevanzanpassungen und nahtlose Schemaänderungen vornehmen.
Lassen Sie uns zunächst das Schema anpassen, um es in Aktion zu erleben.
Melden Sie sich bei App Search an, öffnen Sie die Engine video-games
und klicken Sie auf Schema unter dem Bereich Manage.
Das Schema wird geöffnet. Alle elf Felder werden standardmäßig als text behandelt.
Im Objekt configurationOptions
haben wir zwei Bereichs-Facets definiert, um Zahlen durchsuchen zu können: user_score
und critic_score
. Bereichs-Facet-Felder müssen als Felder des Typs number definiert sein, damit sie korrekt funktionieren.
Klicken Sie auf das Dropdownmenü neben den einzelnen Feldern, ändern Sie den Typ zu number und klicken Sie auf Update Types:
Die Engine reindexiert die Daten dynamisch. Später, wenn wir die Facettierungskomponenten zu unserem Layout hinzufügen, werden die Bereichsfilter wie erwartet funktionieren. Jetzt kommen wir zum wirklich spannenden Teil.
Dieser Abschnitt ist extrem wichtig
Wir können die Relevanz mit drei wichtigen Funktionen steuern: Synonymen, Kuratierungen und Relevanz-Tuning.
Wählen Sie die einzelnen Funktionen unter dem Abschnitt Search Settings in der Seitenleiste aus:
Synonyme
Manche Menschen fahren ein Auto, andere einen PKW und wieder andere eine Klapperkiste. Das Internet ist global, und Menschen in aller Welt verwenden verschiedenste Wörter für dieselben Dinge. Mit Synonymen können Sie Gruppen von Begriffen erstellen, die dieselbe Bedeutung haben.
Im Fall unserer Suchmaschine für Videospiele wissen wir, dass die Benutzer nach Final Fantasy suchen werden. Vielleicht geben sie stattdessen jedoch FF ein.
Klicken Sie auf Synonyms, wählen Sie Create a Synonym Set aus und geben Sie die Begriffe ein:
Klicken Sie auf Save. Sie können beliebig viele Synonyme hinzufügen.
Anschließend hat der Suchbegriff FF dieselbe Bedeutung wie eine Suche nach Final Fantasy.
Kuratierungen
Kuratierungen sind allseits beliebt. Angenommen, ein Benutzer sucht nach Final Fantasy oder FF. In dieser Reihe gibt es viele Spiele - wie sehen die Ergebnisse aus?
Standardmäßig sehen die Top fünf Ergebnisse wie folgt aus:
1. Final Fantasy VIII
2. Final Fantasy X
3. Final Fantasy Tactics
4. Final Fantasy IX
5. Final Fantasy XIII
Irgendetwas stimmt hier nicht ... Final Fantasy VII war das beste Final Fantasy aller Zeiten. Und Final Fantasy XIII war nicht besonders gut! 😜
Können wir festlegen, dass Benutzer bei der Suche nach Final Fantasy als erstes Ergebnis Final Fantasy VII erhalten sollen? Und können wir Final Fantasy XIII aus unseren Suchergebnissen entfernen?
Selbstverständlich!
Klicken Sie auf Curations und geben Sie eine Abfrage ein: Final Fantasy.
Ziehen Sie anschließend das Final Fantasy VII-Dokument mit dem Bedienelement am linken Rand der Tabelle in den Bereich Promoted Documents. Klicken Sie anschließend auf die Schaltfläche Hide Result (durchgestrichenes Auge) für das Final Fantasy XIII-Dokument:
Wenn unsere Benutzer jetzt nach Final Fantasy oder FF suchen, wird Final Fantasy VII als erstes Ergebnis angezeigt.
Und Final Fantasy XIII wird überhaupt nicht angezeigt. Ha!
Wir können beliebig viele Dokumente hervorheben oder verbergen. Wir können unsere hervorgehobenen Dokumente sogar sortieren, um exakt zu steuern, was an der Spitze der Suchergebnisse angezeigt wird.
Relevanz-Tuning
Klicken Sie auf Relevance Tuning in der Seitenleiste.
Bisher suchen wir nach einem Textfeld: name
. Aber was passiert, wenn unsere Benutzer andere Textfelder durchsuchen möchten, zum Beispiel ein name
-Feld und ein description
-Feld? Unsere Videospieldaten enthalten kein Beschreibungsfeld, daher werden wir einige Dokumente selbst erstellen, um diesen Fall zu simulieren.
Angenommen, wir hätten die folgenden Dokumente:
{ "name":"Magical Quest", "description": "A dangerous journey through caves and such." }, { "name":"Dangerous Quest", "description": "A magical journey filled with magical magic. Highly magic." }
Um das Spiel Magical Quest zu finden, könnte ein Benutzer diesen Begriff als Abfrage eingeben. Aber das erste Ergebnis wäre Dangerous Quest:
Warum? Weil das Wort „magical“ in der Beschreibung von Dangerous Quest dreimal enthalten ist und die Suchmaschine nicht weiß, dass ein Feld wichtiger ist als ein anderes. Daher erhält Dangerous Quest einen höheren Rang. Aus diesem Dilemma ist das Relevanz-Tuning entstanden.
Wir können ein Feld auswählen und unter anderem seine Relevanzgewichtung erhöhen:
Wenn wir die Gewichtung erhöhen, steigt das Element auf der rechten Seite - Magical Quest - nach oben, weil das Feld name
stärker berücksichtigt wird. Wir ziehen den Schieberegler also auf einen höheren Wert und klicken auf Save.
Mit App Search haben wir bisher Folgendes erreicht:
- Wir haben das Schema angepasst und
user_score
undcritic_score
als number-Felder deklariert. - Wir haben das Relevanzmodell angepasst.
Und das waren unsere praktischen Dashboard-Funktionen, jeweils mit einem passenden API-Endpunkt, den Sie für programmgesteuerte Funktionen nutzen können, falls sie nichts von GUIs halten.
Lassen Sie uns jetzt die UI fertigstellen.
Der letzte Schliff
Ihre Benutzeroberfläche sollte jetzt funktionsfähig sein. Probieren Sie einige Suchabfragen aus und spielen Sie ein bisschen herum. Was zuerst ins Auge sticht, ist das Fehlen von Tools zur Erkundung unserer Ergebnisse, wie Filter, Facets, Sortiermöglichkeiten und so weiter. Aber die Suche funktioniert. Als Nächstes werden wir die Benutzeroberfläche erweitern.
In der ursprünglichen src/App.js
-Datei haben wir drei wichtige Komponenten importiert:
import { SearchProvider, Results, SearchBox } from "@elastic/react-search-ui";
Wir werden noch einige weitere Komponenten hinzufügen, die zu unseren Konfigurationsoptionen passen.
Importieren Sie die folgenden Komponenten, um die fehlenden Funktionen in der UI hinzuzufügen:
PagingInfo
: Zeigt Informationen zur aktuellen Seite an.ResultsPerPage
: Legt fest, wie viele Ergebnisse pro Seite angezeigt werden.Paging
: Navigation zwischen den Seiten.Facet
: Einzigartige Filter und Erkundungsfunktionen für den jeweiligen Datentyp.Sorting
: Neuausrichtung der Ergebnisse nach einem bestimmten Feld.
import { PagingInfo, ResultsPerPage, Paging, Facet, SearchProvider, Results, SearchBox, Sorting } from "@elastic/react-search-ui";
Die importierten Komponenten können im Layout abgelegt werden.
Die Layout
-Komponente unterteilt die Seite in Abschnitte, und die Komponenten können mit Props in den Abschnitten abgelegt werden.
Die folgenden Abschnitte sind verfügbar:
header
: Suchfeld/-LeistebodyContent
: ErgebniscontainersideContent
: Seitenleiste mit Facets und SortieroptionenbodyHeader
: Wrapper für die Ergebnisse mit umfassenden Kontextinformationen wie aktuelle Seite und Ergebnisse pro SeitebodyFooter
: Paginierungsoptionen für die schnelle Navigation zwischen Seiten
Die Komponenten stellen Daten grafisch dar. Die Daten werden auf Basis der Sucheinstellungen abgerufen, die wir in den configurationOptions angegeben haben. Wir legen die Komponenten jetzt in den passenden Layoutbereichen ab.
Wir haben beispielsweise fünf Faceting-Dimensionen in den configurationOptions
beschrieben, also erstellen wir Facet
-Komponenten. Jede Facet
-Komponente verwendet ein „field“-Prop als Schlüssel, der zurück zu unseren Daten führt.
Wir legen diese Komponenten im Abschnitt sideContent
ab, zusammen mit unserer Sorting
-Komponente. Danach legen wir die Komponenten Paging
, PagingInfo
und ResultsPerPage
in den jeweils passenden Abschnitten ab:
<Layout header={<SearchBox />} bodyContent={<Results titleField="name" urlField="image_url" />} sideContent={ <div> <Sorting label={"Sort by"} sortOptions={[ { name: "Relevance", value: "", direction: "" }, { name: "Name", value: "name", direction: "asc" } ]} /> <Facet field="user_score" label="User Score" /> <Facet field="critic_score" label="Critic Score" /> <Facet field="genre" label="Genre" /> <Facet field="publisher" label="Publisher" isFilterable={true} /> <Facet field="platform" label="Platform" /> </div> } bodyHeader={ <> <PagingInfo /> <ResultsPerPage /> </> } bodyFooter={<Paging />} />
Anschließend können wir uns das Sucherlebnis in der lokalen Entwicklungsumgebung ansehen.
Viel besser! Wir können unsere Suchergebnisse mit leistungsstarken Optionen erkunden.
Dazu haben wir einige nette Extras wie etwa die Mehrfachsortierung, und das Publisher-Facet wird durch Angabe eines einzigen Flags filterbar gemacht. Starten Sie eine Suche mit einer leeren Abfrage und probieren Sie sämtliche Optionen aus.
Zum Abschluss sehen wir uns eine letzte Funktion in unserem Sucherlebnis an. Eine sehr beliebte Funktion ...
Die Autovervollständigung.
Du autovervollständigst mich
Die Autovervollständigung ist bei den Benutzern so beliebt, weil sie sofortiges Feedback liefert. Die Vorschläge sind in zwei Varianten verfügbar: result und query. Je nach Variante erhalten die Benutzer entweder relevante Ergebnisse oder potenzielle Abfragen, die zu den Ergebnissen führen.
In unserem Fall verwenden wir die Autovervollständigung, um Abfragevorschläge anzuzeigen.
Dazu nehmen wir zwei schnelle Änderungen vor.
Zunächst fügen wir die Autovervollständigung zum configurationOptions
-Objekt hinzu:
const configurationOptions = { autocompleteQuery: { suggestions: { types: { documents: { // Welche Felder möchten wir nach Vorschlägen durchsuchen? fields: ["name"] } }, // Wie viele Vorschläge sollen angezeigt werden? size: 5 } }, ... };
Anschließend müssen wir die Autovervollständigung als Funktion der SearchBox
aktivieren:
... <Layout ... header={<SearchBox autocompleteSuggestions={true} />} /> ...
Und das war’s auch schon.
Probieren Sie eine Suche aus. Bei der Eingabe werden die Autovervollständigungs-Vorschläge angezeigt.
Zusammenfassung
Damit haben wir ein ansprechendes und funktionstüchtiges Sucherlebnis erstellt. Außerdem haben wir eine ganze Reihe von Fallstricken umgangen, auf die man bei der Implementierung einer Suchfunktion normalerweise achten muss. Nicht übel für 30 Minuten, was meinen Sie?
Search UI ist ein flexibles und modernes React-Framework, mit dem Sie Sucherlebnisse im Handumdrehen entwickeln können. Elastic App Search ist eine robuste Suchmaschine, die auf Elasticsearch basiert. Sie ist als zahlungspflichtiger, verwalteter Dienst verfügbar oder kann mit einer weitreichenden einfachen Lizenz kostenlos selbst gehostet werden.
Wir sind neugierig darauf, was Sie mit Search UI entwickeln werden. Schauen Sie auf Gitter vorbei, falls Sie einen Beitrag zum Projekt leisten möchten!