Jemand tippt drei Buchstaben in Ihr Suchfeld, bekommt nichts zurück und geht. Sie sehen es nie passieren. Sie sehen nur Wochen später die Absprungrate in den Analytics und schieben es auf die Landingpage.
Suche ist keine Funktion, die man am Ende dranklebt. In einem Shop oder auf einer Buchungsplattform ist sie das Handlungsstärkste, was jemand tun kann. Er sagt Ihnen genau, was er will. Lassen Sie ihn warten, oder bestrafen Sie ihn für einen vertippten Buchstaben, und Sie haben einen Verkauf weggeworfen, den Sie schon halb sicher hatten.
Wir haben inzwischen Suche für ein paar Produkte gebaut. Am meisten gelernt haben wir bei einer App zur Buchung von Parkplätzen. Hier steht, was wir geändert haben, was zuerst kaputtging, und die Zahlen, die den Ausschlag gaben.
Wir haben auf der Datenbank angefangen, wie alle
Die erste Version dieser Suche war eine Datenbankabfrage. Filter, ein paar Joins, Distanzberechnung, ein ORDER BY. Sie funktionierte. Eine Weile.
Dann wurde die Karte voll, und sie funktionierte nicht mehr. Wir kämpften, um die Abfrage unter 500ms zu halten, und jeder Filter, den ein Nutzer setzte, machte sie schwerer. Unter Last war es schlimmer. Man kann sich mit Indizes ein Stück weit rausoptimieren, wir haben es versucht, aber man poliert das falsche Werkzeug. Eine relationale Datenbank ist nicht dafür gebaut, unscharfen Text zu ranken und zehntausend Punkte nach Entfernung zu sortieren, während jemand die Karte herumzieht. Sie tut es. Schnell tut sie es nicht.
Das ist die ehrliche Version. Wir haben eine Woche damit verbracht, das Falsche ein bisschen weniger langsam zu machen, bevor wir zugaben, dass es das Falsche war.
Was Meilisearch wirklich ist
Meilisearch ist eine quelloffene Suchmaschine, geschrieben in Rust. Sie füttern sie mit Dokumenten, sie baut einen Index, sie beantwortet Abfragen in wenigen Dutzend Millisekunden. Tippfehlertoleranz ist standardmäßig an: Ein Wort mit fünf Zeichen verzeiht einen Tippfehler, eins mit neun Zeichen verzeiht zwei, also findet "Tlefon" auch "Telefon", und Sie konfigurieren nichts. Facettenfilter, Synonyme und Geosuche sind alle dabei, hinter einer sauberen REST API.
Die Zahl, die zählt, liegt unter 50ms. Kein Bestwert an einem guten Tag. Der Standard. Das ist der ganze Unterschied zwischen Suche, die sich sofort anfühlt, und Suche, die sich wie Warten anfühlt.
Behalten Sie es als Index, nicht als zweite Datenbank
Hier ist die Meinung, die ich verteidige. Meilisearch ist Ihr Suchindex. Es ist nicht Ihre Datenbank. Lassen Sie es nicht dazu werden.
Wenn eine Abfrage läuft, gibt Meilisearch die Primärschlüssel der passenden Dokumente zurück. Mehr nicht. In Laravel nimmt Scout diese Schlüssel und holt die vollständigen Datensätze direkt aus Ihrer Datenbank, mit einem einzigen whereIn. Sie suchen in Meili, Sie lesen aus Postgres. Index und Quelle der Wahrheit bleiben getrennt.
Das haben wir mit Absicht gemacht, und ich würde es wieder tun. Jedes Feld, das Sie in den Index kopieren, ist ein weiteres Feld außerhalb Ihrer Datenbank, in einem anderen System, das Sie jetzt absichern und mitdenken müssen. Schieben Sie Ihr ganzes Modell hinein, passieren zwei Dinge: Der Index bläht sich auf und wird langsam, und Sie haben sensible Daten still über einen Dienst verstreut, der nur eine Zeile finden sollte. Legen Sie hinein, was die Suche zum Finden und Ranken braucht. Den Rest lassen Sie in der Datenbank, wo er hingehört. Scout macht genau das zum bequemsten Weg, was selten ist und Anerkennung verdient.
Wo es sich ausgezahlt hat: die Karte
Die Volltextseite nimmt man fast als selbstverständlich hin, bis man auf das Problem trifft, das sie sauber löst. Bei uns war das die Karte.
Die Interaktion klingt trivial und ist mühsam, sie gut zu bauen. Nadel setzen, Radius wählen, jeden freien Platz darin bekommen, nächster zuerst, und das Ganze aktuell halten, während man die Karte herumschiebt. Der Radius geht bis 8000 Meter, ein belebtes Viertel sind also viele Kandidaten, die bei jedem kleinen Schwenk sortiert werden wollen.
Meilisearch bringt Geo von Haus aus mit. Sie speichern ein _geo Feld an jedem Dokument, markieren es als filter- und sortierbar, und _geoRadius(lat, lng, meters) gibt Ihnen alles im Kreis. Sortieren Sie nach _geoPoint(lat, lng):asc, kommen die Ergebnisse nach Entfernung geordnet zurück, jedes mit einem _geoDistance in Metern. Kein PostGIS. Keine handgeschriebene Haversine-Formel, in einer Abfrage vergraben. Kein Streit mit dem Query-Planer.
Das Erste, was dem Kunden auffiel, war gar keine Funktion. Die Karte fühlte sich einfach flüssig an. Schwenken und Suchen waren nicht mehr zwei langsame Schritte, sondern eine Bewegung. Dafür bedankt sich niemand. Die Leute hören nur auf zu gehen, was dasselbe ist, nur anders gemessen.
Die Zahl
Das ist der Teil für den skeptischen Entwickler, weil ich einer war.
Vorher: diese Datenbankabfrage, im Kampf um die 500ms, unter Last schlechter. Nachher: 35ms im Schnitt. Kein herausgepickter Bestfall, der Schnitt. Die komplexe Abfrage, die früher nahe einer halben Sekunde lag, antwortet jetzt, bevor der Finger die Karte verlässt. Das ist mehr als eine Verzehnfachung, und es kam daher, die Arbeit auf ein Werkzeug zu verlegen, das dafür gebaut ist, statt härter auf dem zu schuften, das es nicht war.
Man nimmt an, so ein Sprung braucht ein Rewrite. Brauchte er nicht. Die eigentliche Arbeit ist, die Suchlast von der Datenbank zu nehmen und auf eine Engine zu legen, die eine Aufgabe hat.
Der Index hält sich von selbst synchron
Der übliche Einwand gegen eine eigene Suchmaschine ist der naheliegende. Jetzt haben Sie zwei Speicher, und die driften.
Mit Laravel Scout verschwindet das größtenteils. Ein Trait ans Eloquent Modell, sagen welche Felder durchsuchbar sind, und Scout hält den Index aktuell, während Zeilen angelegt, geändert und gelöscht werden. Updates laufen über Ihre Queue, Indexierung blockiert also nie einen Web-Request. Soft Deletes sind abgedeckt. Im Alltag hören Sie auf, den Index als etwas zu sehen, das Sie pflegen. Sie ändern einen Datensatz, der Index zieht nach. Das ist der Punkt.
Wo Vektoren ins Spiel kommen
Tippfehlertolerante Volltextsuche deckt das meiste ab, was Leute tippen. Aber Absicht ist unordentlicher als Stichwörter. In der Parkplatz-App suchen Leute quer durcheinander: eine Straße, ein Tag, eine Eigenschaft des Platzes, manchmal den Namen des Platzes selbst. Solche Abfragen liegen nicht sauber auf den genauen Wörtern in Ihren Daten, und keine Tippfehlertoleranz rettet eine Abfrage, die kein Wort mit dem Datensatz teilt, den sie treffen soll.
Da verdient sich semantische Suche ihren Platz. Seit 1.3 speichert Meilisearch Vektor-Embeddings neben Ihren Dokumenten und kann hybride Suche fahren: Stichwort und Bedeutung zusammen. Eine Abfrage ohne ein gemeinsames Wort findet den Datensatz trotzdem, weil sie sich in der Bedeutung nah sind. Die Embeddings machen Sie mit einem Modell Ihrer Wahl, Meili hält und durchsucht sie. Mein Rat: Erst solide Volltextsuche ausliefern, semantische Suche obendrauf, wenn die unordentlichen Abfragen in den Logs auftauchen. Sie reißen dafür nichts heraus.
Warum sich das im Verkauf zeigt
Ganz nüchtern. Eine Suche, die langsam ist oder nichts liefert, sobald sich jemand vertippt, ist ein Leck. Niemand beschwert sich. Die Leute gehen, und Sie erfahren nie, warum.
Seit der Umstellung heißt eine Suche ohne Ergebnis: Es gibt wirklich keinen passenden Datensatz. Nicht ein falscher Buchstabe. Nicht eine Abfrage, die etwas anders formuliert ist als die Daten. Das ist das ganze Spiel. Das Feld soll zurückgeben, was der Mensch meinte, schnell genug, dass er nie ans Feld denkt. Jede Suche, die das Richtige findet, ist ein Mensch, der geblieben ist. Ein guter Teil derer, die bleiben, kauft.
Schnelle, fehlertolerante Suche fühlt sich nie wie ein Wachstumshebel an, weil sie unsichtbar ist, wenn sie funktioniert. Genau deshalb wird sie übersprungen.
Wo Conimex IT ins Spiel kommt
Wenn Ihre Website-Suche eine LIKE Abfrage ist, die Tippfehler bestraft, oder Ihre Karte ruckelt, oder Ihre Analytics voll sind mit Suchen, die leer zurückkamen, dann ist das lösbar, und es braucht selten das Rewrite, auf das Sie sich schon einstellen. Wir bauen Suche für Shops und Web-Apps auf Meilisearch und Laravel: Volltext mit Tippfehlertoleranz und Synonymen, Geosuche für Karten und Standort, sauberes Scout-Indexing, das Ihrer Datenbank folgt, und hybride semantische Suche, wenn die Abfragen die Absicht treffen müssen und nicht nur die Wörter. Wenn das nach einem Leck klingt, das Sie lieber schließen, melden Sie sich, und wir schauen uns an, was Ihre Suche Sie still kostet.
