2012-10-17 5 views
10

A seguito di this answer voglio sapere qual è il modo migliore per utilizzare di PostgreSQL incorporato ricerca a testo integrale è se voglio ordinare per rango, e limite alla query solo corrispondenti .modo migliore per utilizzare PostgreSQL ricerca a testo integrale classifica

Assumiamo una tabella molto semplice.

CREATE TABLE pictures { 
    id SERIAL PRIMARY KEY, 
    title varchar(300), 
    ... 
} 

o qualsiasi altra cosa. Ora voglio cercare nel campo title. Per prima cosa creare un indice:

CREATE INDEX pictures_title ON pictures USING gin(to_tsvector('english', title)); 

Ora voglio cercare 'small dog'. Questo funziona:

SELECT pictures.id, ts_rank_cd(to_tsvector('english', pictures.title), 'small dog') AS score 
FROM pictures 
ORDER BY score DESC 

Ma quello che voglio veramente è questo:

SELECT pictures.id, ts_rank_cd(to_tsvector('english', pictures.title), to_tsquery('small dog')) AS score 
FROM pictures WHERE to_tsvector('english', pictures.title) @@ to_tsquery('small dog') 
ORDER BY score DESC 

Oppure, in alternativa questo (che non funziona - non può utilizzare score nella clausola WHERE):

SELECT pictures.id, ts_rank_cd(to_tsvector('english', pictures.title), to_tsquery('small dog')) AS score 
FROM pictures WHERE score > 0 
ORDER BY score DESC 

Qual è il modo migliore per farlo? Le mie domande sono numerosi:

  1. Se uso la versione con ripetuti to_tsvector(...) intende chiamare che per due volte, o è abbastanza intelligente per mettere in cache i risultati in qualche modo?
  2. C'è un modo per farlo senza ripetere le chiamate di funzione to_ts...?
  3. C'è un modo per utilizzare score nella clausola WHERE?
  4. In caso affermativo, sarebbe meglio filtrare per score > 0 o utilizzare la cosa @@?

risposta

10
select * 
from (
    SELECT 
     pictures.id, 
     ts_rank_cd(to_tsvector('english', pictures.title), 
     to_tsquery('small dog')) AS score 
    FROM pictures 
) s 
WHERE score > 0 
ORDER BY score DESC 
5

Se uso la versione con ripetuti to_tsvector (...) si è chiamata che per due volte, o è abbastanza intelligente per mettere in cache i risultati in qualche modo?

Il modo migliore per notare queste cose è fare una semplice spiegazione, anche se queste possono essere difficili da leggere.

Per farla breve, sì, PostgreSQL è abbastanza intelligente da riutilizzare i risultati calcolati.

C'è un modo per farlo senza ripetere le chiamate alla funzione to_ts ...?

Quello che faccio di solito è aggiungere una colonna tsv che è il vettore di ricerca testo. Se si effettua questo aggiornamento automatico utilizzando i trigger, si ottiene immediatamente il vettore facilmente accessibile, ma consente anche di aggiornare in modo selettivo l'indice di ricerca rendendo selettivo il trigger.

C'è un modo per utilizzare punteggio nella clausola WHERE?

Sì, ma non con quel nome. In alternativa potresti creare una sotto-query, ma personalmente la ripeterò.

Se c'è, sarebbe meglio filtrare per punteggio> 0 o usare la cosa @@?

La versione più semplice che posso pensare è questo:

SELECT * 
FROM pictures 
WHERE 'small dog' @@ text_search_vector 

Il text_search_vector potrebbe ovviamente essere sostituito con qualcosa di simile to_tsvector('english', pictures.title)

+0

Questa risposta ignora ciò che seemse di essere la parte più importante della questione: "classifica" – steviejay