Wie erstellt man einfache unscharfe Suche nur mit Postgresql?
Ich habe ein kleines problem mit der Suchfunktion auf meiner RoR-basierte Website. Ich habe viele Produkte mit einigen CODEs. Dieser code kann ein beliebiger string sein, wie "AB-123-lHdfj". Ich benutze jetzt ILIKE-operator, Produkte zu finden:
Product.where("code ILIKE ?", "%" + params[:search] + "%")
Es funktioniert, aber es nicht finden können Produkt-codes wie z.B. "AB123-lHdfj", oder "AB123lHdfj".
Was soll ich tun? Kann postgresql hat einige string-Normalisierung, oder einige andere Methoden, um mir zu helfen? 🙂
InformationsquelleAutor der Frage Alve | 2011-10-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Postgres stellt ein Modul mit mehreren string-Vergleich-Funktionen wie soundex und metaphone. Aber Sie wollen die die levenshtein - edit-Distanz-Funktion.
Den
2
ist die edit-Distanz zwischen zwei Wörtern. Wenn Sie dieses gegen eine Reihe von Worten und Sortieren Sie durch die edit-Distanz Ergebnis haben Sie die Art von fuzzy-matches, die Sie suchen.Versuchen, diese Abfrage Beispiel: (mit eigenem Objekt-Namen und-Daten natürlich)
Diese Abfrage sagt:
Mir die top 10 Ergebnisse alle Daten aus some_table, wo die edit-Distanz zwischen den code-Wert und der Eingang 'AB123-lHdfj' ist kleiner als 3. Sie werden wieder alle Zeilen wo der Wert von code ist innerhalb von 3 Zeichen Unterschied zu 'AB123-lHdfj'...
Hinweis: wenn Sie einen Fehler wie:
Installieren Sie die
fuzzystrmatch
Erweiterung mit:InformationsquelleAutor der Antwort Paul Sasik
Paul Ihnen erzählt
levenshtein()
. Das ist ein sehr nützliches Werkzeug, aber es ist auch sehr langsam, mit großen Tischen. Es hat zur Berechnung der levenshtein-Abstand der Suchbegriff für jede einzelne Zeile, die ist teuer.First off, wenn deine Anforderungen sind so einfach wie das Beispiel zeigt, können Sie immer noch
LIKE
. Ersetzen Sie einfach alle-
in Ihren Suchbegriff mit%
zu erstellen, dieWHERE
Klauselstatt
Wenn Ihr wirkliche problem ist komplexer und Sie brauchen etwas schneller, was dann - je nach Ihren Anforderungen gibt es mehrere Möglichkeiten.
Es ist Volltextsuchenatürlich. Aber vielleicht ist das ein overkill in deinem Fall.
Ein wahrscheinlicher Kandidat ist pg_trgm. Beachten Sie, dass können Sie kombinieren, dass mit
LIKE
in PostgreSQL 9.1. Sehen Sie diese blog-post von Depesz.Auch sehr interessant in diesem Zusammenhang: die
similarity()
Funktion oder%
Betreiber des betreffenden Moduls. Mehr:Nicht zuletzt können Sie implementieren eine hand-stricken-Lösung mit einer Funktion zu normalisieren die Zeichenfolgen gesucht werden. Zum Beispiel könnten Sie transformieren
AB1-23-lHdfj
->ab123lhdfj
speichern Sie es in eine zusätzliche Spalte ein, und suchen Sie mit den Suchbegriffen, die transformiert wurden auf die gleiche Weise.Oder verwenden Sie eine index auf einem Ausdruck anstelle der redundanten Spalte. (Beteiligten Funktionen muss
IMMUTABLE
.) Und eventuell zu kombinieren, dass mitpg_tgrm
von oben.Übersicht der pattern-matching-Techniken:
InformationsquelleAutor der Antwort Erwin Brandstetter