|
|
|||
Volltextsuche mit PostgreSQLViele Programmierer waren schon frustriert, weil eine
Tsearch2 liefert einige neue Datentypen und Funktionen, mit welchen gearbeitet werden SELECT 'Der erste String zum testen '::tsvector; tsvector --------------------------------------- 'Der' 'zum' 'erste' 'String' 'testen' (1 ROW) Als Ergebnis bekommen wir alle Wörter des Strings. Wörter, welche SELECT 'Der erste String zum testen und testen '::tsvector; tsvector --------------------------------------------- 'Der' 'und' 'zum' 'erste' 'String' 'testen' (1 ROW) Um das ganze mal etwas praktischer anzugehen, legen wir uns als erstes CREATE TABLE messages ( id int4, message text); Und wir brauchen auch noch Inhalte… INSERT INTO messages VALUES ('1', 'Dies ist eine Testnachricht'); INSERT INTO messages VALUES ('2', 'Dumdidum Nachricht'); INSERT INTO messages VALUES ('3', 'Ich bin ein Blindtext'); Jetzt haben wir ein Paar Daten in der Tabelle, aber noch keine Möglichkeit ALTER TABLE messages ADD COLUMN idxFTI tsvector; Um das Feld die neue Spalte initial zu füllen sollte man wie folgt vorgehen:
Als erstes erzeugen wir den Volltextindex aus der Spalte message und UPDATE messages SET idxFTI=to_tsvector('default',message); VACUUM FULL ANALYZE; Wenn z.B. mehrere Spalten in den Volltextindex aufgenommen werden sollen, UPDATE messages SET idxFTI=to_tsvector('default',COALESCE(message,'') ||' '|| COALESCE(andereSpalte,'')); VACUUM FULL ANALYZE; Jetzt erzeugen wir einen normalen Index auf der Spalte idxFTI… CREATE INDEX idxFTI_idx ON messages USING gist(idxFTI); VACUUM FULL ANALYZE; Im Prinzip kann man schon jetzt per Volltext suchen. Eine Suche nach SELECT id, message FROM messages WHERE idxfti @@ 'ein'::tsquery; id | message -------+----------------------------- 1 | Dies ist eine Testnachricht 3 | Ich bin ein Blindtext (2 ROWS) Wie aber erzeugen wir den Inhalt von idxFTI, wenn ein neuer CREATE OR REPLACE FUNCTION vectorupdate() RETURNS TRIGGER AS $vectorupdate$ BEGIN UPDATE messages SET idxFTI=to_tsvector('default',message) WHERE id=NEW.id; RETURN NEW; END; $vectorupdate$ LANGUAGE plpgsql; CREATE TRIGGER tgr_vectorupdate AFTER INSERT OR UPDATE ON messages FOR EACH ROW EXECUTE PROCEDURE vectorupdate(); Wenn jetzt ein neuer Datensatz eingetragen bzw. verändert wird, dann Natürlich war dies nur ein kurzer Abriss von tsearch2, für den |
|||
Copyright © 2009 treibsand.com. All Rights Reserved |
|||
8 Kommentare zu “Volltextsuche mit PostgreSQL”
hiho,
nettes Beispiel, funktioniert nur leider nicht. Befolgt man die Anleitung Schritt für Schritt, wird alles zwar mit Erfolg erstellt, die Suche ist jedoch ergebnislos. In der idxFTI-Spalte ist nach dem Aufbau des Index auch nichts drin, ich vermute das das nicht so sein soll, oder?
Ich vermute, dass dann der Trigger nicht ausgeführt wird, welcher nach dem insert oder update anspringen sollte. Hast du mal manuell versucht die idxFTI Spalte zu erzeugen?
Nein, habe ich noch nicht… die spalte wird aber doch erzeugt, nur eben nicht gefüllt.
bei der Anleitung hier knallt es schon wenn ich
UPDATE messages SET idxFTI=to_tsvector(‘default’,message);
mache, da die Konfiguration default nicht existiert. Wenn ich diese anlegen möchte, dann gibt es einen Fehler. Nur wenn ich diese irgendwie anders nenne, dann gehts, später wird die idxFTI eben nicht gefüllt.
PS: um den Trigger geht es auch noch nicht… nach dem zweiten Vacuum versuche ich zu selecten:
SELECT id, message FROM messages WHERE idxfti @@ ‘ein’::tsquery;
=> liefert keine Ergebnisse
Ich meinte eigentlich den Inhalt von idxFTI mit einem manuellen Update füllen…
Probier mal…
UPDATE messages SET idxFTI=to_tsvector(‘simple’,message);
das hat funktioniert, warum verstehe ich jedoch nicht wirklich. Es gibt wohl unterschiedliche Standard-Konfigurationen wie “default” und “simple” nach denen die idxFTI aufgebaut werden kann?
PS: nun knallt es im Trigger nach einen neuen Insert.
FEHLER: Grenze für Stacktiefe überschritten
HINT: Erhöhen Sie den Konfigurationsparameter »maxstackdepth«, nachdem Sie sichergestellt haben, dass die Stacktiefenbegrenzung Ihrer Plattform ausreichend ist.
FEHLER: Grenze für Stacktiefe überschritten
HINT: Erhöhen Sie den Konfigurationsparameter »maxstackdepth«, nachdem Sie sichergestellt haben, dass die Stacktiefenbegrenzung Ihrer Plattform ausreichend ist.
CONTEXT: SQL-Anweisung »UPDATE messages SET idxFTI=totsvector(‘simple’,message) WHERE id= $1 «
PL/pgSQL function “vectorupdate” line 2 at SQL-Anweisung
SQL-Anweisung »UPDATE messages SET idxFTI=totsvector(‘simple’,message) WHERE id= $1 «
PL/pgSQL function “vectorupdate” line 2 at SQL-Anweisung
SQL-Anweisung »UPDATE messages SET idxFTI=to_tsvector(‘simple’,message) WHERE id= $1 «
nach langer Suche funktioniert bei mir folgende Funktion:
CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE
ON messages FOR EACH ROW EXECUTE PROCEDURE
tsvectorupdatetrigger(idxfti, ‘pg_catalog.german’, message);
wichtig ist vor ALLEM das Before und nicht das After insert da sonst eine Endlosschleife ausgelöst wird.
Interessant…bei mir wird der Trigger nach dem Update ausgeführt, was prima funktioniert.
In meiner DB mach ich das Update allerdings etwas anders, da ich ein Bytea Feld verwende. Ich wollte nämlich eine Volltextsuche in der DBMail Datenbank realisieren…
UPDATE dbmailmessageblks
SET idxFTI=totsvector(‘simple’,encode(messageblk, ‘escape’)) where messageblk
idnr=NEW.messageblkidnr;
Das Update kann nämlich auf die Nase fallen, wenn das Encoding nicht stimmt.
Kommentar hinzufügen