PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie indiziert man eine Postgres-Tabelle nach Namen, wenn der Name in jeder Sprache sein kann?

Wenn Sie willkürliche Teilstring-Übereinstimmungen optimieren möchten, besteht eine Möglichkeit darin, den pg_tgrm Modul . Index hinzufügen:

CREATE INDEX table_location_name_trigrams_key ON table
  USING gin (location_name gin_trgm_ops);

Dadurch wird "Simple Cafe" in "sim", "imp", "mpl" usw. aufgeteilt und dem Index für jedes Trigam in jeder Zeile ein Eintrag hinzugefügt. Der Abfrageplaner kann diesen Index dann automatisch für Musterübereinstimmungen von Teilzeichenfolgen verwenden, einschließlich:

SELECT * FROM table WHERE location_name ILIKE '%cafe%';

Diese Abfrage wird im Index nach „caf“ und „afe“ suchen, die Schnittmenge finden, diese Zeilen abrufen und dann jede Zeile mit Ihrem Muster vergleichen. (Diese letzte Überprüfung ist notwendig, da die Schnittmenge von „caf“ und „afe“ sowohl mit „simple cafe“ als auch mit „unsafe scaffolding“ übereinstimmt, während „%cafe%“ nur mit einem übereinstimmen sollte). Der Index wird effektiver, wenn das Eingabemuster länger wird, da er mehr Zeilen ausschließen kann, aber er ist immer noch nicht so effizient wie das Indizieren ganzer Wörter, erwarten Sie also keine Leistungsverbesserung gegenüber to_tsvector .

Der Haken an der Sache ist, dass Trigramme überhaupt nicht für Muster mit weniger als drei Zeichen funktionieren. Das kann ein Deal-Breaker für Ihre Bewerbung sein oder auch nicht.

Bearbeiten: Ich habe dies ursprünglich als Kommentar hinzugefügt.

Ich hatte letzte Nacht einen anderen Gedanken, als ich meistens schlief. Erstellen Sie ein cjk_chars Funktion, die eine Eingabezeichenfolge akzeptiert, regexp_matches den gesamten CJK-Unicode-Bereich und gibt ein Array solcher Zeichen oder NULL zurück wenn keine. Fügen Sie einen GIN-Index zu cjk_chars(location_name) hinzu . Dann fragen Sie nach:

WHERE CASE
  WHEN cjk_chars('query') IS NOT NULL THEN
    cjk_chars(location_name) @> cjk_chars('query')
    AND location_name LIKE '%query%'
  ELSE
    <tsvector/trigrams>
  END

Ta-da, Unigramme!