
Bei grösseren Websites und vor allem unseren E-Commerce Projekten war es immer wieder ein Thema: Die Suchfunktion – und warum sie so schlecht ist. Die letzten zwei Monate haben wir einige Massnahmen getroffen, damit man endlich findet, was man sucht.
Inhalte in diesem Beitrag
Auslegung der Probleme
Rauszufinden, was an den Standard Suchfunktionen von WordPress nicht gut ist, fällt nicht schwer. Was wir angehen müssen ist:
- Tippfehler erkennen und korrigieren.
- Autovervollständigung von erfolgreichen Suchbegriffen.
- Volltextsuche und daraus folgende Relevanzsortierung.
- Index um Wortabwandlungen (Plurale, Synonyme) erweitern.
- Zusätzliche Metadaten erzeugen und indexieren.
- Shops: Tiefe integration in den Filter.
Schritt für Schritt zum Ziel
Nach Analyse der verwendeten Suchbegriffe sehen wir Tippfehler als eines der akuten Probleme. Ganz oft gibt es Buchstabendreher, die mit minimaler Intelligenz in der Software korrigiert werden können. Um das zu ermöglichen, müssen wir eine Liste mit korrekten Wörtern haben: Ich habe also einen Index erstellt, der alle Wörter in der gesamten Datenbank enthält, sowie einige Zusatzinformationen wie die Anzahl der Zeichen, die Wortart (sofern möglich) und wie oft das Wort vorkommt.
Mittels einer Kombination der PHP-Funktionen similar_text()
und levenshtein()
habe ich dann eine Funktion gebaut, die aufgrund des Indexes mögliche Korrekturvorschläge liefert. Durch similar_text()
ist es sogar möglich, diese nach „Grad der Übereinstimmung“ zu sortieren. Zu einfachen Buchstabendrehern, aber teilweise auch bei gröberen Schreibfehlern, kann ich so mit grosser Wahrscheinlichkeit das oder die Wörter finden, die der Besucher tippen wollte.
Wörter, die wir in der Datenbank nicht kennen, kann ich so jedoch nicht korrigieren. Doch das ist fürs Erste nicht schlimm, denn ein nicht bekanntes Wort würde in der Suche sowieso zu keinem Ergebnis führen.
Autovervollständigung
Hierbei handelt es sich eher um ein Komfort-Feature, doch es ist nicht unwichtig. Manchmal versucht man, etwas zu finden, weiss aber nicht genau, wonach man suchen muss. Da wir Suchanfragen aufzeichnen und auch deren Ergebnisse kennen, kann ich nun beim Tippen des Suchbegriffs bereits Vergleiche anstellen mit vormals erfolgreichen Suchanfragen. Hierbei habe ich priorisiert, dass gleich beginnende Zeichenketten zuerst erscheinen, danach solche, die mittels similar_text()
hinzugefügt werden. Gibt man nun „Tell“ ein, zeige ich die relevantesten Suchanfragen an, wie „Teller Dessert“, „Teller rot“ oder eben auch „Suppenteller“.
Diese Funktion planen wir im weiteren Verlauf der Optimierungen noch weiter zu verbessern. Je mehr Informationen wir hier aufzeichnen können, desto mehr lernen wir und schliesslich auch die Software, wie und wonach die Leute suchen.
Volltextsuche und Relevanzsortierung
Zugegeben, vor diesem Projekt war mir gar nicht klar, was ein Volltextindex in einer SQL-Datenbank eigentlich genau ist. Es ist nicht das gleiche wie ein Index – ich dachte einfach, dass es genau das ist: ein Index für eine Spalte mit Text, also dem Datentyp CHAR, VARCHAR oder TEXT. Ähnlich, aber nicht ganz.
Ein wesentlicher Punkt ist, dass man einen Volltextindex über mehrere Spalten erstellen kann. Das kann, sofern man genau das will, erübrigen, dass man über mehrere Felder mit OR und LIKE sucht, was gerade bei mehr als einem Wort in einem Suchbegriff schnell schwierig wird. Und genau deshalb funktioniert auch die WordPress-Suche mit einem Begriff ganz okay, aber bei mehreren Worten wird’s schon schwierig. Einen Volltextindex hat WordPress weder auf der „posts“- noch auf der „postmeta“-Tabelle.
Grössere Pläne
Im ersten Schritt wollte ich einfach einen Volltextindex über die Titel-, Exzerpt- und Content-Felder erstellen. Doch ich hatte noch ein paar weitere Ideen, um den Index zu füllen. Auch Informationen aus den Kategorien, Schlagworten oder – bei Produkten – deren gesamten Eigenschaften müssen in den Index. Teilweise auch Metadaten, die sonst schwer oder gar nicht auffindbar wären. Und wir leben ja im Zeitalter der KI – warum also nicht auch noch eine oder zwei Spalten von einer KI erzeugen lassen?
All das habe ich getan, in einer eigenen Tabelle, die speziell als Suchindex dient. Besonders eingehen möchte ich auf Letzteres: Mit der ChatGPT-API übergeben wir einen Prompt mit den Informationen zu unserem Inhalt – dies kann ein Beitrag, ein Produkt oder irgendein kundenspezifischer Datentyp sein. Diese Informationen und den vorhandenen Text gebe ich automatisch ChatGPT, um daraus weitere Informationen zu erzeugen.
- Eine eigene Zusammenfassung aus dem gesamten Inhalt – zusätzlich zu der Zusammenfassung, die wir möglicherweise bereits in der Datenbank haben. Falls eine vorhanden ist, bitten ich ChatGPT, möglichst Wortalternativen zum Original zu verwenden und die Zusammenfassung stichhaltiger zu formulieren.
- Gerade aus Metadaten und Kategorien erzeuge ich zudem Synonyme und Plurale. So findet man einen Weinkelch dann auch unter Weinglas oder Rotweinglas – je nach Durchmesser. Man findet nicht nur „Teller rot“, sondern auch „rote Teller“. Wobei Letzteres auch schon durch die „Schreibfehlerkorrektur“ behandelt wird. Das klappt aber nicht immer mit jeder Farbe oder Eigenschaft, daher kommt diese Information zusätzlich in den Index.
Die Index-Struktur
Ich muss nun selbst definieren, ob ich einen Volltextindex über alle Spalten erstelle oder mehrere Spalten in verschiedene Indizes aufteile. Ich weiss, dass ich mit MATCH
und AGAINST
in SQL meinen Index (oder mehrere) mittels OR
abfragen kann. Wenn ich die Indizes trenne, habe ich die Möglichkeit, einem Index in der Sortierung nach Relevanz mehr Gewicht zu geben.
Im ersten Schritt hatten wir pro Spalte einen eigenen Volltextindex. Das führte zu einem langen Statement mit vielen OR
-Bedingungen und einer entsprechend längeren Relevanzberechnung – diese übernimmt MariaDB (wahrscheinlich auch MySQL und jedes andere Datenbanksystem) automatisch bei der Nutzung eines Volltextindex. Die Berechnung fällt je nach Modus unterschiedlich aus, abhängig davon, ob der „Natural Language“- oder der „Boolean“-Mode verwendet wird. Auch hier musste ich zunächst einige Tests durchführen.
Derzeit habe ich es auf zwei Volltextindizes beschränkt: Einen für die eigenen Inhaltsfelder und einen für die von der KI hinzugefügten Inhalte. Je nach Anzahl der Suchwörter und deren Länge wechsle ich im SQL-Statement automatisch zwischen den beiden Modi, da jeder je nach Suchbegriff seine eigenen Vor- und Nachteile hat.
Tiefe Integration in den Filter
Wie man es aus Onlineshops kennt, kommen sowohl auf Kategorieseiten als auch auf Suchergebnisseiten Filter zum Einsatz, um die Ergebnisse weiter einzuschränken. Ich experimentiere derzeit damit, einzelne Suchwörter aus der Anfrage bei (fast) eindeutigen Ergebnissen automatisch einem passenden Suchfilter zuzuordnen und diesen direkt zu aktivieren.
Gibt jemand beispielsweise „Fussball Übungen Torhüter“ ein, selektieren wir automatisch die Kategorie „Fussball“ sowie die Inhaltsart „Übung“ und durchsuchen die gesamte Datenbank nach Inhalten, in denen eines bis alle dieser drei Wörter vorkommen – sinnvoll nach Relevanz sortiert. In Onlineshops führt dies oft dazu, dass ein allgemeinerer Suchbegriff direkt auf eine Farbe und/oder ein Material eingeschränkt wird. So erkennt der Nutzer sofort, dass er den Filter anpassen und nach weiteren Eigenschaften einschränken kann. Eine voreingestellte Farbe wie „Rot“ kann dann beispielsweise entfernt und durch „Violett“ ersetzt oder ergänzt werden.
Ich plane, dieses Konzept auch für Suchbegriffe mit Zahlen einzuführen – das ist allerdings ein eigenes kleines Projekt. Eine Suche nach „Trinkglas 1,5 – 3 dl“ soll künftig nicht mehr zu „Keine Resultate“ führen sondern Trinkgläser finden mit genau diesem Bereich an Fassungsvermögen. Die kontinuierliche Verbesserung der Suchfunktion steht bei mir regelmässig auf dem Plan, damit die Kunden unserer Kunden genau das finden, wonach sie suchen.

Auf deiner Website wird auch nicht alles gefunden?
Tausch dich unverbindlich mit Michael aus.