2012-12-30 13 views
9

Sto usando pg_search per cercare del testo all'interno del mio modello. Tra gli altri attributi, ho un campo url.Separatori di parole per la ricerca di testo completo di Postgres con Rails

Unfortuantelly Postgres non sembra per identificare / e . come separatori di parola, quindi non posso cercare all'interno del url.

Esempio: la ricerca di test in http://test.com non produce risultati.

C'è un modo per risolvere questo problema, magari usando un altro gioiello o qualche SQL in linea?

+0

come un work-around si potrebbe avere un'altra colonna/attributo con l'url e separatori di parole riconosciute, e la ricerca contro che invece – AJcodez

risposta

0

ho finito per modificare la gemma pg_search per supportare le espressioni ts_vector arbitrarie al posto dei nomi appena colonna. I cambiamenti sono here

Ora posso scrivere:

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

Come indicato nella documentazione (e notato da AJcodez), esiste una soluzione nella creazione di una colonna dedicata per l'indice tsvector. Quindi definire un trigger che cattura gli inserimenti a URL indicizzare correttamente:

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

Questo metodo sarà transorm tutti i caratteri non alfabetici in unico spazio e girare la stringa in un tsvector:

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

Ora creare un trigger che chiama questa funzione:

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(); 

Ora, quando vengono inseriti URL, il campo `url_tsvectorè verrà popolato automaticamente.

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) 

Per la ricerca FT sugli URL è sufficiente eseguire una query su questo campo.

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

Non lo sai anche bisogno della colonna in più se si utilizza un [indice funzionale] (http://www.postgresql.org/docs/8.4/static/indexes-expressional.html). Inoltre, è possibile creare una [visualizzazione] (http://www.postgresql.org/docs/8.4/static/tutorial-views.html) per evitare la necessità di specificare la forma completa dell'espressione utilizzata per creare l'indice quando eseguire una query. –

+0

Ho hackerato quella gemma per supportare le chiamate arbitrarie di ts_vector, che mi permetteranno di usare 'regexp_replace', come suggerito. L'utilizzo dei trigger di inserimento/aggiornamento potrebbe avere il vantaggio delle prestazioni, ma trovo questa soluzione un po 'ingombrante per le mie esigenze. Grazie per l'aiuto. – mihai

Problemi correlati