そのためにアクセントのないモジュールを使用してください-これは、リンクしているものとは完全に異なります。
unaccentは、語彙素からアクセント(発音区別符号)を削除するテキスト検索辞書です。
データベースごとに1回インストールします。
CREATE EXTENSION unaccent;
次のようなエラーが発生した場合:
ERROR: could not open extension control file
"/usr/share/postgresql/<version>/extension/unaccent.control": No such file or directory
この関連する回答の指示に従って、データベースサーバーにcontribパッケージをインストールします。
unaccent()
特に、例で使用できる関数を提供します(LIKE
不要と思われる場合)。
SELECT *
FROM users
WHERE unaccent(name) = unaccent('João');
索引
この種のクエリにインデックスを使用するには、式にインデックスを作成します。ただしIMMUTABLE
、Postgresはインデックスの関数のみを受け入れます。関数が同じ入力に対して異なる結果を返す可能性がある場合、インデックスは黙って壊れることがあります。
unaccent()
だけでSTABLE
はないIMMUTABLE
残念ながら、unaccent()
は、ではSTABLE
ありませんIMMUTABLE
。pgsql-bugsに関するこのスレッドによると、これは3つの理由によるものです。
- 辞書の振る舞いに依存します。
- この辞書への有線接続はありません。
- したがって、電流にも依存し、
search_path
簡単に変化する可能性があります。
Web上のいくつかのチュートリアルでは、関数のボラティリティをに変更するように指示されていIMMUTABLE
ます。このブルートフォース方式は、特定の条件下で機能しなくなる可能性があります。
他の人は単純なIMMUTABLE
ラッパー関数を提案します(私が過去に自分でやったように)。
使用される辞書を明示的に宣言する2つのパラメーターを使用してバリアント を作成するかどうかについては、現在も議論が続いています。ここまたはここIMMUTABLE
を読んでください。
もう1つの代替手段は、Githubで提供されているMusicbrainzによるIMMUTABLEunaccent()
関数を備えたこのモジュールです。自分でテストしたことはありません。私はより良いアイデアを思いついたと思います:
今のところベスト
このアプローチは、他のソリューションが浮かんでいるのでより効率的で、より安全です。ハードワイヤードスキーマ修飾関数とディクショナリを使用して2パラメーター形式を実行するSQLラッパー関数
を作成します。IMMUTABLE
不変でない関数をネストすると関数のインライン化が無効になるため、(偽の)C関数のコピーにも基づいて宣言IMMUTABLE
します。その唯一の目的は、SQL関数ラッパーで使用することです。単独で使用するためのものではありません。
C関数の宣言で辞書を配線する方法がないため、高度な機能が必要です。(Cコード自体をハックする必要があります。)SQLラッパー関数はそれを行い、関数のインライン化と式のインデックスの両方を許可します。
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$;
PARALLEL SAFE
Postgres9.5以前の両方の機能から削除します。
public
拡張機能をインストールしたスキーマです(public
デフォルトです)。
明示的な型宣言(regdictionary
)は、悪意のあるユーザーによる関数のオーバーロードされたバリアントによる架空の攻撃から防御します。
以前は、アクセントのないモジュールに付属しているSTABLE
関数に基づいたラッパー関数を提唱していました。unaccent()
その無効化された関数のインライン化。このバージョンは、以前ここにあった単純なラッパー関数よりも10倍高速に実行されます。
そして、それは、関数に追加された最初のバージョンの2倍の速さでしSET search_path = public, pg_temp
た。辞書もスキーマ修飾できることがわかるまでは。それでも(Postgres 12)ドキュメントからはあまり明白ではありません。
C関数を作成するために必要な特権がない場合は、次善の実装に戻ります。モジュールによって提供される関数のIMMUTABLE
関数ラッパー:STABLE
unaccent()
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;
最後に、クエリを高速化するための式インデックス:
CREATE INDEX users_unaccent_name_idx ON users(public.f_unaccent(name));
インデックスを再作成しないインプレースメジャーリリースアップグレードのように、関数またはディクショナリを変更した後は、この関数に関連するインデックスを再作成することを忘れないでください。最近のメジャーリリースにはすべて、unaccent
モジュールの更新がありました。
インデックスに一致するようにクエリを調整します(クエリプランナーがそれを使用するようにします)。
SELECT * FROM users
WHERE f_unaccent(name) = f_unaccent('João');
正しい式の関数は必要ありません。そこでは、直接のようにアクセントのない文字列を提供することもできます'Joao'
。
より高速な関数は、式インデックスを使用したはるかに高速なクエリには変換されません。これは事前に計算された値で動作し、すでに非常に高速です。ただし、インデックスの保守と、インデックスを使用しないクエリには利点があります。
クライアントプログラムのセキュリティは、Postgres 10.3 / 9.6.8などで強化されています。インデックスで使用する場合に示すように、関数とディクショナリ名をスキーマ修飾する必要があります。見る:
合字
Postgres 9.5以前では、「Œ」や「ß」などの合字は、unaccent()
常に1文字に置き換えられるため、手動で展開する必要があります(必要な場合)。
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
E A e a S
Postgres9.6でのアクセントのないこのアップデートを気に入るはずです。
contrib/unaccent
の標準unaccent.rules
ファイルを拡張して、Unicodeで認識されているすべての発音区別符号を処理し、合字を正しく展開します(Thomas Munro、LéonardBenedetti)
大胆な強調鉱山。今、私たちは得る:
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
OE AE oe ae ss
パターンマッチング
任意のパターンの場合、LIKE
または任意のパターンで、これをPostgreSQL9.1以降ILIKE
のモジュールと組み合わせます。pg_trgm
トリグラムGIN(通常は望ましい)またはGIST式インデックスを作成します。GINの例:
CREATE INDEX users_unaccent_name_trgm_idx ON users
USING gin (f_unaccent(name) gin_trgm_ops);
次のようなクエリに使用できます。
SELECT * FROM users
WHERE f_unaccent(name) LIKE ('%' || f_unaccent('João') || '%');
GINおよびGISTインデックスは、プレーンなbtreeよりも維持に費用がかかります。
左に固定されたパターンには、より簡単な解決策があります。パターンマッチングとパフォーマンスの詳細:
pg_trgm
また、「類似性」(%
)と「距離」(<->
)の便利な演算子も提供します。
トリグラムインデックスは、~
etalを使用した単純な正規表現もサポートしています。大文字と小文字を区別しないパターンマッチングILIKE
: