Hvis du ønsker at optimere vilkårlige understreng-matches, er en mulighed at bruge
CREATE INDEX table_location_name_trigrams_key ON table
USING gin (location_name gin_trgm_ops);
Dette vil opdele "Simple Cafe" i "sim", "imp", "mpl" osv., og tilføje en post til indekset for hver trigam i hver række. Forespørgselsplanlæggeren kan derefter automatisk bruge dette indeks til understrengmønstermatches, herunder:
SELECT * FROM table WHERE location_name ILIKE '%cafe%';
Denne forespørgsel vil slå "caf" og "afe" op i indekset, finde krydset, hente disse rækker og derefter kontrollere hver række mod dit mønster. (Den sidste kontrol er nødvendig, da skæringspunktet mellem "caf" og "afe" matcher både "simpel cafe" og "usikre stilladser", mens "%cafe%" kun skal matche én). Indekset bliver mere effektivt, efterhånden som inputmønsteret bliver længere, da det kan udelukke flere rækker, men det er stadig ikke så effektivt som at indeksere hele ord, så forvent ikke en præstationsforbedring i forhold til to_tsvector
.
Fangst er, at trigrammer slet ikke virker for mønstre, der er under tre tegn. Det er måske eller ikke en deal-breaker for din ansøgning.
Rediger: Jeg tilføjede først dette som en kommentar.
Jeg fik en anden tanke i går aftes, da jeg for det meste sov. Lav en cjk_chars
funktion, der tager en inputstreng, regexp_matches
hele CJK Unicode-intervallerne og returnerer en matrix af sådanne tegn eller NULL
hvis ingen. Tilføj et GIN-indeks på cjk_chars(location_name)
. Spørg derefter efter:
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, unigrams!