Użyj do tego modułu bez akcentu - który jest zupełnie inny niż to, do którego tworzysz link.
unaccent to słownik wyszukiwania tekstu, który usuwa akcenty (znaki diakrytyczne) z leksemów.
Zainstaluj raz na bazę danych za pomocą:
CREATE EXTENSION unaccent;
Jeśli pojawi się błąd, taki jak:
ERROR: could not open extension control file
"/usr/share/postgresql/<version>/extension/unaccent.control": No such file or directory
Zainstaluj pakiet Contrib na serwerze bazy danych, zgodnie z instrukcją w tej powiązanej odpowiedzi:
Między innymi zapewnia funkcję, unaccent()
której możesz użyć na swoim przykładzie (gdzie LIKE
wydaje się, że nie jest potrzebna).
SELECT *
FROM users
WHERE unaccent(name) = unaccent('João');
Indeks
Aby użyć indeksu dla tego rodzaju zapytania, utwórz indeks dla wyrażenia . Jednak Postgres akceptuje tylko IMMUTABLE
funkcje dla indeksów. Jeśli funkcja może zwrócić inny wynik dla tego samego wejścia, indeks może po cichu przerwać.
unaccent()
tylko STABLE
nieIMMUTABLE
Niestety unaccent()
tylko STABLE
nie IMMUTABLE
. Zgodnie z tym wątkiem dotyczącym błędów pgsql , wynika to z trzech powodów:
- Zależy to od zachowania słownika.
- Nie ma stałego połączenia z tym słownikiem.
- Zależy to zatem również od prądu
search_path
, który może się łatwo zmieniać.
Niektóre samouczki w sieci WWW zalecają zmianę zmienności funkcji na IMMUTABLE
. Ta metoda brutalnej siły może się zepsuć w pewnych warunkach.
Inni sugerują prostą IMMUTABLE
funkcję opakowującą (tak jak ja robiłem to w przeszłości).
Trwa debata, czy utworzyć wariant z dwoma parametrami, IMMUTABLE
który jawnie deklaruje używany słownik. Przeczytaj tutaj lub tutaj .
Inną alternatywą byłoby moduł z niezmiennymi unaccent()
funkcji przez Musicbrainz , umieszczonych na Github. Sam tego nie testowałem. Myślę, że wpadłem na lepszy pomysł :
Na razie najlepsze
Takie podejście jest bardziej wydajne niż inne rozwiązania i bezpieczniejsze .
Utwórz funkcję IMMUTABLE
opakowującą SQL wykonującą formularz dwuparametrowy z okablowaną funkcją kwalifikowaną schematu i słownikiem.
Od gniazdowania non-niezmienny funkcję spowodowałoby wyłączenie funkcji inline, baza go na kopii C-funkcji (fałszywej) ogłosił IMMUTABLE
również. Jego jedynym celem jest użycie w opakowaniu funkcji SQL. Nie jest przeznaczony do samodzielnego użytku.
Wymagane jest wyrafinowanie, ponieważ nie ma sposobu na trwałe połączenie słownika w deklaracji funkcji C. (Wymagałoby to zhakowania samego kodu C.) Funkcja opakowująca SQL robi to i umożliwia zarówno wstawianie funkcji, jak i indeksy wyrażeń.
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$;
Usuń PARALLEL SAFE
z obu funkcji dla Postgres 9.5 lub starszych.
public
jest schematem, w którym zainstalowałeś rozszerzenie ( public
jest to ustawienie domyślne).
Jawna deklaracja typu ( regdictionary
) chroni przed hipotetycznymi atakami z przeciążonymi wariantami funkcji ze strony złośliwych użytkowników.
Wcześniej opowiadałem się za funkcją opakowującą opartą na STABLE
funkcji unaccent()
dostarczanej z modułem unaccent. Ta wyłączona funkcja inlining . Ta wersja wykonuje dziesięć razy szybciej niż prosta funkcja opakowująca, którą miałem tutaj wcześniej.
Było to już dwa razy szybsze niż pierwsza wersja, która została dodana SET search_path = public, pg_temp
do funkcji - dopóki nie odkryłem, że słownik również może być kwalifikowany według schematu. Jednak (Postgres 12) nie jest zbyt oczywiste z dokumentacji.
Jeśli nie masz uprawnień niezbędnych do tworzenia funkcji w C, wracasz do drugiej najlepszej implementacji: IMMUTABLE
opakowania funkcji wokół STABLE
unaccent()
funkcji udostępnianej przez moduł:
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;
Na koniec indeks wyrażeń do szybkiego wykonywania zapytań :
CREATE INDEX users_unaccent_name_idx ON users(public.f_unaccent(name));
Pamiętaj o ponownym utworzeniu indeksów obejmujących tę funkcję po każdej zmianie funkcji lub słownika, na przykład po uaktualnieniu głównej wersji w miejscu, które nie spowoduje odtworzenia indeksów. Wszystkie ostatnie główne wydania zawierały aktualizacje unaccent
modułu.
Dostosuj zapytania do indeksu (aby planista zapytań go użył):
SELECT * FROM users
WHERE f_unaccent(name) = f_unaccent('João');
Nie potrzebujesz funkcji w odpowiednim wyrażeniu. Można tam również dostarczyć sznurki bez akcentu, jak 'Joao'
bezpośrednio.
Szybsza funkcja nie przekłada się na znacznie szybsze zapytania korzystające z indeksu wyrażenia . To działa na wstępnie obliczonych wartościach i jest już bardzo szybkie. Ale utrzymanie indeksu i zapytania nie korzystają z indeksu.
Zabezpieczeń dla programów klienckich zostały dokręcone PostgreSQL 10,3 / 9.6.8 itp Państwo potrzebują do schematu zakwalifikować funkcję i nazwę słownika, jak wykazano w przypadku stosowania w dowolnych pozycjach. Widzieć:
Ligatury
W Postgres 9.5 lub starszych ligaturach, takich jak `` Œ '' lub `` ß '', należy rozszerzyć ręcznie (jeśli jest to potrzebne), ponieważ unaccent()
zawsze zastępuje jedną literę:
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
E A e a S
Spodoba ci się ta aktualizacja, która zniknęła w Postgres 9.6 :
Rozszerz contrib/unaccent
standardowy unaccent.rules
plik, aby obsługiwał wszystkie znaki diakrytyczne znane w Unicode i poprawnie rozszerzaj ligatury (Thomas Munro, Léonard Benedetti)
Odważne podkreślenie moje. Teraz otrzymujemy:
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
OE AE oe ae ss
Dopasowanie wzorców
Dla LIKE
lub ILIKE
z dowolnymi wzorcami, połącz to z modułem pg_trgm
w PostgreSQL 9.1 lub nowszym. Utwórz trygram GIN (zazwyczaj preferowany) lub indeks wyrażenia GIST. Przykład dla WZ:
CREATE INDEX users_unaccent_name_trgm_idx ON users
USING gin (f_unaccent(name) gin_trgm_ops);
Może być używany do zapytań takich jak:
SELECT * FROM users
WHERE f_unaccent(name) LIKE ('%' || f_unaccent('João') || '%');
Indeksy GIN i GIST są droższe w utrzymaniu niż zwykłe btree:
Istnieją prostsze rozwiązania dla wzorów zakotwiczonych w lewo. Więcej o dopasowywaniu wzorców i wydajności:
pg_trgm
zawiera również przydatne operatory dla „podobieństwa” ( %
) i „odległości” ( <->
) .
Indeksy Trigram obsługują również proste wyrażenia regularne z ~
et al. i dopasowywanie wzorca bez rozróżniania wielkości liter z ILIKE
: