Se desideri ottimizzare le corrispondenze arbitrarie di sottostringhe, un'opzione consiste nell'usare il pg_tgrm
modulo
. Aggiungi un indice:
CREATE INDEX table_location_name_trigrams_key ON table
USING gin (location_name gin_trgm_ops);
Questo suddividerà "Simple Cafe" in "sim", "imp", "mpl", ecc. e aggiungerà una voce all'indice per ogni trigam in ogni riga. Il pianificatore di query può quindi utilizzare automaticamente questo indice per le corrispondenze del modello di sottostringa, tra cui:
SELECT * FROM table WHERE location_name ILIKE '%cafe%';
Questa query cercherà "caf" e "afe" nell'indice, troverà l'intersezione, recupererà quelle righe, quindi verificherà ogni riga rispetto al tuo modello. (Quell'ultimo controllo è necessario poiché l'intersezione di "caf" e "afe" corrisponde sia a "cafè semplice" che a "impalcatura non sicura", mentre "%cafe%" dovrebbe corrispondere solo a uno). L'indice diventa più efficace man mano che il pattern di input si allunga poiché può escludere più righe, ma non è ancora efficiente quanto l'indicizzazione di intere parole, quindi non aspettarti un miglioramento delle prestazioni rispetto a to_tsvector
.
Il problema è che i trigrammi non funzionano affatto per i modelli con meno di tre caratteri. Questo potrebbe essere o meno un problema per la tua applicazione.
Modifica: Inizialmente l'ho aggiunto come commento.
Ho avuto un altro pensiero la scorsa notte, quando ero per lo più addormentato. Crea un cjk_chars
funzione che accetta una stringa di input, regexp_matches
l'intero intervallo CJK Unicode e restituisce un array di tali caratteri o NULL
se nessuno. Aggiungi un indice GIN su cjk_chars(location_name)
. Quindi eseguire una query per:
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, unigram!