Použijte modul unaccent za to – což je úplně jiné než to, na co odkazujete.
unaccent je slovník pro vyhledávání v textu, který odstraňuje diakritická znaménka z lexémů.
Nainstalujte jednou na databázi pomocí:
CREATE EXTENSION unaccent;
Pokud se zobrazí chyba jako:
ERROR: could not open extension control file "/usr/share/postgresql/<version>/extension/unaccent.control": No such file or directory
Nainstalujte balíček contrib na svůj databázový server podle pokynů v této související odpovědi:
- Chyba při vytváření nezvýrazněného rozšíření na PostgreSQL
Mimo jiné poskytuje funkci unaccent()
můžete použít ve svém příkladu (kde ILIKE
zdá se, že to není potřeba).
SELECT *
FROM users
WHERE unaccent(name) = unaccent('João');
Index
Chcete-li pro tento druh dotazu použít index, vytvořte pro výraz index. Nicméně , Postgres přijímá pouze IMMUTABLE
funkce pro indexy. Pokud funkce může vrátit jiný výsledek pro stejný vstup, index se může tiše zlomit.
unaccent()
pouze STABLE
není IMMUTABLE
Bohužel unaccent()
je pouze STABLE
, nikoli IMMUTABLE
. Podle tohoto vlákna na pgsql-bugs je to kvůli třem důvody:
- Záleží na chování slovníku.
- K tomuto slovníku není žádné pevné připojení.
- Záleží tedy také na aktuální
search_path
, který se může snadno změnit.
Některé výukové programy na webu doporučují pouze změnit volatilitu funkce na IMMUTABLE
. Tato metoda hrubé síly se může za určitých podmínek zlomit.
Jiní navrhují jednoduchý IMMUTABLE
funkce wrapper (jako jsem to dělal v minulosti).
Probíhá debata, zda udělat variantu se dvěma parametry IMMUTABLE
který použitý slovník výslovně deklaruje. Přečtěte si zde nebo zde.
Další alternativou by byl tento modul s IMMUTABLE unaccent()
funkce Musicbrainz, poskytovaná na Github. Sám jsem to netestoval. Myslím, že jsem přišel na lepší nápad :
Zatím nejlepší
Tento přístup je efektivnější než ostatní řešení a bezpečnější .
Vytvořte IMMUTABLE
Funkce SQL wrapper spouštějící dvouparametrový formulář s pevně zapojenou funkcí a slovníkem kvalifikovanou pro schéma.
Protože vnoření neměnné funkce by znemožnilo vkládání funkce, založte ji na kopii C-funkce (falešné) deklarované IMMUTABLE
také. Jeho pouze Účelem je použití v obalu funkce SQL. Není určeno k použití samostatně.
Je zapotřebí sofistikovanosti, protože neexistuje způsob, jak pevně zapojit slovník do deklarace funkce C. (Vyžadovalo by hacknutí samotného kódu C.) Funkce SQL wrapper to dělá a umožňuje vkládání funkcí a indexy výrazů.
CREATE OR REPLACE FUNCTION public.immutable_unaccent(regdictionary, text)
RETURNS text LANGUAGE c IMMUTABLE PARALLEL SAFE STRICT AS
'$libdir/unaccent', 'unaccent_dict';
CREATE OR REPLACE FUNCTION public.f_unaccent(text)
RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
$func$
SELECT public.immutable_unaccent(regdictionary 'public.unaccent', $1)
$func$;
Pusťte PARALLEL SAFE
z obou funkcí pro Postgres 9.5 nebo starší.
public
je schéma, do kterého jste rozšíření nainstalovali (public
je výchozí).
Explicitní deklarace typu (regdictionary
) chrání před hypotetickými útoky přetíženými variantami funkce ze strany uživatelů se zlými úmysly.
Dříve jsem obhajoval funkci wrapper založenou na STABLE
funkce unaccent()
dodáváno s unaccent modulem. Tato deaktivovaná funkce vkládání. Tato verze se spustí desetkrát rychleji než jednoduchá funkce wrapper, kterou jsem zde měl dříve.
A to už bylo dvakrát rychlejší než první verze, která přidala SET search_path = public, pg_temp
k funkci - dokud jsem nezjistil, že slovník lze také kvalifikovat podle schématu. Přesto (Postgres 12) není z dokumentace příliš zřejmé.
Pokud chybí vám potřebná oprávnění k vytváření funkcí C, jste zpět u druhé nejlepší implementace:IMMUTABLE
funkce wrapper kolem STABLE
unaccent()
funkce poskytovaná modulem:
CREATE OR REPLACE FUNCTION public.f_unaccent(text)
RETURNS text AS
$func$
SELECT public.unaccent('public.unaccent', $1) -- schema-qualify function and dictionary
$func$ LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT;
Nakonec index výrazů aby byly dotazy rychlé :
CREATE INDEX users_unaccent_name_idx ON users(public.f_unaccent(name));
Nezapomeňte znovu vytvořit indexy zahrnout tuto funkci po jakékoli změně funkce nebo slovníku, jako je upgrade hlavní verze na místě, který by nevytvářel indexy. Všechny poslední hlavní verze obsahovaly aktualizace pro unaccent
modul.
Přizpůsobte dotazy tak, aby odpovídaly indexu (takže je použije plánovač dotazů):
SELECT * FROM users
WHERE f_unaccent(name) = f_unaccent('João');
Nepotřebujete funkci ve správném výrazu. Zde můžete také zadat řetězce bez akcentu jako 'Joao'
přímo.
Rychlejší funkce se nepřevádí na mnohem rychlejší dotazy pomocí indexu výrazů . To funguje na předem vypočítaných hodnotách a je již velmi rychlé. Ale údržba indexu a dotazy nevyužívají výhody indexu.
Zabezpečení klientských programů bylo posíleno s Postgres 10.3 / 9.6.8 atd. potřebujete k určení funkce a názvu slovníku podle schématu, jak je ukázáno při použití v jakýchkoli indexech. Viz:
- „slovník textového vyhledávání „nepřízvuk“ neexistuje' záznamy v protokolu postgres, pravděpodobně během automatické analýzy
Ligy
V Postgres 9.5 nebo starší ligatury jako 'Œ' nebo 'ß' je třeba rozbalit ručně (pokud to potřebujete), protože unaccent()
vždy nahradí single písmeno:
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
E A e a S
Tato aktualizace se vám v Postgres 9.6 bude líbit :
Rozšířit
contrib/unaccent
standardníunaccent.rules
pro zpracování všech diakritik známých Unicode a správné rozbalení ligatur (ThomasMunro, Léonard Benedetti)
Odvážný důraz můj. Nyní dostáváme:
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
OE AE oe ae ss
Shoda vzorů
Za ILIKE
nebo ILIKE
s libovolnými vzory, zkombinujte to s modulem pg_trgm
v PostgreSQL 9.1 nebo novějším. Vytvořte trigramový GIN (obvykle preferovaný) nebo výrazový index GIST. Příklad pro GIN:
CREATE INDEX users_unaccent_name_trgm_idx ON users
USING gin (f_unaccent(name) gin_trgm_ops);
Lze použít pro dotazy jako:
SELECT * FROM users
WHERE f_unaccent(name) LIKE ('%' || f_unaccent('João') || '%');
Udržování indexů GIN a GIST je dražší než prostý btree:
- Rozdíl mezi indexem GiST a GIN
Pro pouze vlevo ukotvené vzory existují jednodušší řešení. Více o porovnávání vzorů a výkonu:
- Shoda vzoru s LIKE, SIMILAR TO nebo regulárními výrazy v PostgreSQL
pg_trgm
také poskytuje užitečné operátory pro "podobnost" (%
) a "vzdálenost" (<->
).
Trigram indexy také podporují jednoduché regulární výrazy s ~
a kol. a nerozlišují se malá a velká písmena shoda vzoru s ILIKE
:
- Přízvuk v PostgreSQL + vyhledávání bez rozlišení velkých a malých písmen