Si vous souhaitez optimiser les correspondances de sous-chaînes arbitraires, une option consiste à utiliser le pg_tgrm
modules
. Ajouter un index :
CREATE INDEX table_location_name_trigrams_key ON table
USING gin (location_name gin_trgm_ops);
Cela décomposera "Simple Cafe" en "sim", "imp", "mpl", etc., et ajoutera une entrée à l'index pour chaque trigam dans chaque ligne. Le planificateur de requêtes peut alors utiliser automatiquement cet index pour les correspondances de modèles de sous-chaînes, notamment :
SELECT * FROM table WHERE location_name ILIKE '%cafe%';
Cette requête recherchera "caf" et "afe" dans l'index, trouvera l'intersection, récupérera ces lignes, puis vérifiera chaque ligne par rapport à votre modèle. (Cette dernière vérification est nécessaire car l'intersection de "caf" et "afe" correspond à la fois à "café simple" et à "échafaudage dangereux", tandis que "%cafe%" ne doit correspondre qu'à un seul). L'index devient plus efficace à mesure que le modèle d'entrée s'allonge car il peut exclure plus de lignes, mais il n'est toujours pas aussi efficace que l'indexation de mots entiers, alors ne vous attendez pas à une amélioration des performances par rapport à to_tsvector
.
Le hic, c'est que les trigrammes ne fonctionnent pas du tout pour les motifs de moins de trois caractères. Cela peut ou non être un facteur décisif pour votre application.
Modifier : J'ai d'abord ajouté ceci en tant que commentaire.
J'ai eu une autre pensée la nuit dernière alors que je dormais presque. Faire un cjk_chars
fonction qui prend une chaîne d'entrée, regexp_matches
l'ensemble des plages CJK Unicode et renvoie un tableau de ces caractères ou NULL
si aucun. Ajouter un index GIN sur cjk_chars(location_name)
. Ensuite, recherchez :
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, unigrammes !