新しいモジュールを使用する そのために-これはあなたがリンクしているものとは完全に異なります。
unaccentは、語彙素からアクセント(diacriticsigns)を削除するテキスト検索辞書です。
データベースごとに1回インストールします:
CREATE EXTENSION unaccent;
次のようなエラーが発生した場合:
ERROR: could not open extension control file "/usr/share/postgresql/<version>/extension/unaccent.control": No such file or directory
この関連する回答の指示に従って、データベースサーバーにcontribパッケージをインストールします。
- PostgreSQLでアクセントのない拡張機能を作成する際のエラー
特に、関数unaccent()
を提供します 例で使用できます(LIKE
必要ないようです。
SELECT *
FROM users
WHERE unaccent(name) = unaccent('João');
インデックス
この種のクエリにインデックスを使用するには、式にインデックスを作成します。 ただし 、PostgresはIMMUTABLE
のみを受け入れます インデックスの関数。関数が同じ入力に対して異なる結果を返す可能性がある場合、インデックスは黙って壊れることがあります。
unaccent()
STABLE
のみ IMMUTABLE
ではありません
残念ながら、unaccent()
STABLE
のみです 、IMMUTABLE
ではありません 。 pgsql-bugsに関するこのスレッドによると、これは3つによるものです。 理由:
- 辞書の動作によって異なります。
- この辞書への有線接続はありません。
- したがって、現在の
search_path
にも依存します 、簡単に変更できます。
Web上の一部のチュートリアルでは、関数のボラティリティをIMMUTABLE
に変更するように指示されています。 。このブルートフォース方式は、特定の条件下で機能しなくなる可能性があります。
単純なIMMUTABLE
を提案する人もいます ラッパー関数(過去に自分で行ったように)
2つのパラメータIMMUTABLE
を使用してバリアントを作成するかどうかについては議論が続いています。 使用される辞書を明示的に宣言します。ここまたはここを読んでください。
別の代替手段は、IMMUTABLE unaccent()
を備えたこのモジュールです。 Githubで提供されるMusicbrainzによる機能。自分でテストしたことはありません。 より良いアイデアを思いついたと思います :
今のところベスト
このアプローチは、他のソリューションが浮かんでいるのでより効率的で、より安全です 。IMMUTABLE
を作成します 配線されたスキーマ修飾関数と辞書を使用して2パラメーター形式を実行するSQLラッパー関数。
不変でない関数をネストすると関数のインライン化が無効になるため、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倍速く実行されます 以前にここで使用した単純なラッパー関数よりも。
これは、SET search_path = public, pg_temp
を追加した最初のバージョンの2倍の速さでした。 関数に-辞書もスキーマ修飾できることがわかるまで。それでも(Postgres 12)ドキュメントからはあまり明白ではありません。
もし C関数を作成するために必要な特権が不足している場合は、2番目に優れた実装である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などで強化されています。必要 任意のインデックスで使用される場合に示されるように、関数とディクショナリ名をスキーマ修飾します。参照:
- 「テキスト検索辞書「unaccent」は存在しません」postgresログのエントリ、おそらく自動分析中
合字
Postgresの場合9.5以前 unaccent()
であるため、「Œ」や「ß」などの合字は手動で展開する必要があります(必要な場合)。 常にシングルに置き換えます 手紙:
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
E A e a S
Postgres 9.6でアクセントがないこのアップデートを気に入るはずです :
contrib/unaccent
を拡張します の標準のunaccent.rules
Unicodeで知られているすべてのdiacriticsを処理し、合字を正しく拡張するためのファイル (ThomasMunro、LéonardBenedetti)
大胆な強調鉱山。今、私たちは得ます:
SELECT unaccent('Œ Æ œ æ ß');
unaccent
----------
OE AE oe ae ss
パターンマッチング
LIKE
の場合 またはILIKE
任意のパターンで、これをモジュール pg_trgm
と組み合わせます PostgreSQL9.1以降。トリグラム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よりも維持に費用がかかります:
- GiSTとGINインデックスの違い
左に固定されたパターンには、より簡単な解決策があります。パターンマッチングとパフォーマンスの詳細:
- PostgreSQLのLIKE、SIMILAR TO、または正規表現とのパターンマッチング
pg_trgm
「類似性」(%
)の便利な演算子も提供します )と「距離」(<->
。
トリグラムインデックスは、~
を使用した単純な正規表現もサポートしています。 etal。および大文字と小文字を区別しない ILIKE
とのパターンマッチング :
- PostgreSQLアクセント+大文字と小文字を区別しない検索