Die beste Antwort auf „Schatz, was essen wir heute?“

Ein Elasticsearch Proof-of-Concept zur Verbesserung der Usability von Suchfunktionen. Oder vereinfacht gesagt: Gemeinsam mit einem Global Player der Online-Bestellung haben wir die Restaurantsuche revolutioniert.

Das Projekt

Unser Kunde, einer der globalen Player im Bereich Online-Bestellungen und Lieferservice von Lebensmitteln, wollte die Art und Weise ändern, wie Benutzer nach Restaurants suchen. Derzeit bietet die Website Restaurantnamen und Postleitzahlen als Filter bei der Suche an. Um aber wettbewerbsfähig zu bleiben und die Nutzerbindung zu verbessern, musste das Suchverhalten durch produktbasierte Filter verbessert werden. Auch aus der Sicht der Endnutzer ist die Mühe bei der Restaurantsuche mit der Art der Küche als erstem und den Artikeln als zweitem Filter einfach zu groß. Wäre es nicht leichter für den Nutzer, einfach das einzugeben, was er gerne essen würde, um dann eine Liste der anbietenden Restaurants zu erhalten?

Angesichts dieses Problems wurde kreuzwerker beauftragt, ein Proof-of-Concept zu erstellen und die Vorteile der Verwendung von Elasticsearch zur Verbesserung der Benutzerfreundlichkeit der Suchfunktion aufzuzeigen.

Das Problem

Das Unternehmen verwaltet Restaurants und Produkte, indem es sie aus einer relationalen Datenbank bedient, die über 12 Millionen Produkte von Restaurants weltweit enthält. Dass es keine eindeutigen Namenskonventionen für Produkte gab, führte zu rund 3 Millionen redundanter Produkte mit unterschiedlicher Schreibweise. Zum Beispiel sind „Pizza Margharita“ und „Pizza Margarita“ semantisch identisch, werden aber unterschiedlich geschrieben und weisen zwei Produkt-IDs auf, die zu zwei unterschiedlichen Restaurants gehören.

Die Herausforderung bestand in der Gruppierung von semantisch ähnlichen Produkten, so dass die Suche auch bei Schreibfehlern im Eingabetext relevante Ergebnisse liefern würde. Da das Unternehmen länderübergreifend tätig ist, beschränkt sich die Suche nicht auf eine Sprache. Die Datenbank enthält die weltweiten Restaurantdaten, weshalb die von uns gesuchten Zeichenfolgen sprachspezifische Buchstaben und Übersetzungen beinhalten konnten. Doch mit der reinen Produktsuche ist es nicht getan. Der Nutzer sollte auch dann nach Restaurantnamen suchen können, wenn der gesuchte Begriff mit einem Restaurant übereinstimmt.

Auf der ETL-Seite mussten die relevanten Produktdaten aus der relationalen Datenbank extrahiert und musste Elasticsearch transformiert und indexiert werden, indem geeignete Logstash-Konfigurationen und Dokumenten-Mappings für eine effiziente Suchperformance durchgeführt wurden. Da dies das nächste große Feature in der Produktpipeline unseres Kunden werden könnte, aber auch im Hinblick auf die Skalierbarkeit, entschlossen wir uns zur Einführung moderner Software-Tools und Workflows, um genau das Feature zu liefern, das sich unser Kunde vorgestellt hatte.

Die Lösung

Die Architektur, die wir für den ETL-Prozess entwickelten, arbeitet mit Logstash, einer serverseitigen Open-Source-Datenverarbeitungspipeline, die Daten aus verschiedenen Quellen aufnimmt, transformiert und an den definierten Elasticsearch-Index sendet. Neben dem Sammeln von Daten aus verschiedenen Systemen leistet Logstash etwas noch Wichtigeres: Es normalisiert verschiedene Schemata auf ein einziges Format, das in den Elasticsearch-Index eingearbeitet werden kann. Die relevanten Daten aus der Datenbank wurden analysiert und Abfragen innerhalb der Logstash-Konfiguration definiert. Zur Verbindung mit der gehosteten Datenbank wurde der AWS Redshift JDBC-Treiber verwendet. Das Rückimportieren der täglichen Datenbankänderungen erfolgte durch das Setzen entsprechender relationaler Abfragen, die die aktuellsten Daten extrahieren, und die Operation wurde automatisiert, um den Elastic-Index mit der primären Datenbank synchron zu halten.

In Elasticsearch (ES) wurde jedes Dokument durch seine Produkt-ID identifiziert und alle relevanten Details für die Suche indiziert. Da sich die Produktdaten nicht auf eine Sprache beschränkten, wurden zur Verbesserung der Suchrelevanz mehrsprachige und phonetische Analysatoren eingesetzt. Außerdem wurde zur Vereinfachung der Wildcard-Suche der ngram tokenizer in das Dokumenten-Mapping implementiert. Bei Änderungen oder Ergänzungen der Produktdaten können Änderungen im ES-Index einfach mit einer Upsert-Operation vorgenommen werden. So ist sichergestellt, dass Aktualisierungen nur erfolgen, wenn das Dokument – identifiziert durch die Produkt-ID – bereits existiert. Andernfalls bewirkt die Indizierung eine Einfügung des neu gefundenen Dokuments.

Nach der Strukturierung der Abfrage-DSL zum Herausfiltern von Restaurants, die das gesuchte Produkt anbieten, auf Basis einer Postleitzahl, wurde in React JS ein Frontend UI entwickelt, um die neue Suchfunktion zu visualisieren. Die Implementierung kann so erweitert werden, dass die Nutzer selbst definierte Abfragen anhand der verschiedenen Produktattribute und -metriken wie Entfernung zu einem Restaurant, Lieferzeit, Bewertung usw. erstellen können.

Schließlich wurde terraform für die Bereitstellung des gesamten Stacks auf AWS (Amazon Web Services) ausgewählt und das Pilotprojekt durchgeführt.

Unser Beitrag

Neben der vorgeschlagenen Architektur wurde eine neue globale Suche nach Produkten und Restaurants mit verbesserten Funktionen eingeführt, was sich positiv auf die Nutzerbindung auswirkt. Der ETL-Prozess mit Logstash-Spiegeln, die Live-Datenbank und die Elasticsearch-Daten werden zu den neuen Änderungen in der Datenbank immer etwas relativ bleiben. Außerdem wurde die ES-Dokumentstruktur, die für Produkte steht, vollständig denormalisiert, um die Schnellabfrage der Ergebnisse zu verbessern. Obwohl das Projekt als Proof-of-Concept gedacht war, wurde die gesamte Architektur unter Berücksichtigung der Skalierbarkeit konzipiert und ist bereits serienreif.

Wir sind stolz darauf, Teil der nächsten großen Produktphase zu sein, und freuen uns, dass wir die Vorteile von AWS Elasticsearch Service als primäre Suchmaschine erkannt und demonstriert haben.