2012-12-30 9 views
9

Ich verwende pg_search für einige Textsuche in meinem Modell. Unter anderen Attributen habe ich ein url Feld.Worttrennzeichen für Postgres-Volltextsuche mit Rails

Leider Postgres scheint nicht / und . als Worttrennzeichen zu identifizieren, daher kann ich nicht innerhalb der url suchen.

Beispiel: Suche nach test in http://test.com ergibt keine Treffer.

Gibt es eine Möglichkeit, dieses Problem zu beheben, vielleicht mit einem anderen Juwel oder Inline-SQL?

+0

als Behelfslösung können Sie eine weitere Spalte/Attribut mit der URL und erkannten Wort-Separatoren, und suchen gegen diese stattdessen – AJcodez

Antwort

0

I beenden das pg_search Juwel Modifikation bis zu beliebigen ts_vector Ausdrücke anstatt nur Spaltennamen zu unterstützen. Die Änderungen sind here

Jetzt kann ich schreiben:

pg_search_scope :search, 
    against: [[:title , 'B'], ["to_tsvector(regexp_replace(url, '[^\\w]+', ' ', 'gi'))", 'A']], 
    using: {tsearch: {dictionary: "simple"}} 
5

Wie in der Dokumentation erwähnt (und von AJcodez bemerkt), gibt es eine Lösung beim Erstellen einer dedizierten Spalte für Tsvector Index. Dann definiert einen Auslöser, der richtig Einfügungen zu indizieren URLs fängt:

CREATE test_url (url varchar NOT NULL, url_tsvector tsvector NOT NULL); 

Dieses Verfahren wird alle nicht alphabetische Zeichen in einzelnen Raum transorm und die Zeichenfolge in eine tsvector drehen:

CREATE OR REPLACE FUNCTION generate_url_tsvector(varchar) 
RETURNS tsvector 
LANGUAGE sql 
AS $_$ 
    SELECT to_tsvector(regexp_replace($1, '[^\w]+', ' ', 'gi')); 
$_$; 

Nun einen Trigger schaffen, die ruft diese Funktion auf:

CREATE OR REPLACE FUNCTION before_insert_test_url() 
RETURNS TRIGGER 
LANGUAGE plpgsql AS $_$ 
BEGIN; 
    NEW.url_tsvector := generate_url_tsvector(NEW.url); 

    RETURN NEW; 
END; 
$_$ 
; 

CREATE TRIGGER before_insert_test_url_trig 
BEFORE INSERT ON test_url 
FOR EACH ROW EXECUTE PROCEDURE before_insert_test_url(); 

Jetzt, wenn die URL eingefügt wird, wird das Feld 'url_tsvectorè' automatisch ausgefüllt.

INSERT INTO test_url (url) VALUES ('http://www.google.fr'); 
TABLE test_url; 

id   url      url_tsvector    

    2 http://www.google.fr 'fr':4 'googl':3 'http':1 'www':2 

(1 row) 

Um FT-Suche auf URLs müssen Sie nur für dieses Feld abfragen.

SELECT * FROM test_url WHERE url_tsvector @@ 'google'::tsquery; 
+1

Sie nicht tun benötigen Sie sogar die zusätzliche Spalte, wenn Sie einen [Funktionsindex] (http://www.postgresql.org/docs/8.4/static/indexes-expressional.html) verwenden. Darüber hinaus können Sie eine [Ansicht] (http://www.postgresql.org/docs/8.4/static/tutorial-views.html) erstellen, um zu vermeiden, dass die vollständige Form des Ausdrucks, der zum Erstellen des Index verwendet wird, angegeben werden muss eine Abfrage durchführen. –

+0

Ich habe dieses Juwel gehackt, um beliebige Aufrufe von ts_vector zu unterstützen, was mir erlaubt, 'regexp_replace' zu ​​verwenden, wie Sie vorgeschlagen haben. Die Verwendung von insert/update-Triggern kann den Vorteil von Leistung haben, aber ich finde diese Lösung für meine Bedürfnisse etwas zu umständlich. Danke für die Hilfe. – mihai