全文検索を使用しながら2つの関数を組み合わせたインデックスを作成することが理にかなっているかどうかを知りたいです:lower(name)
and f_unaccent(name)
ここで_f_unaccent
_は、アクセントをなくすためのラッパーにすぎません関数は不変です。
私は機能しているインデックスがあります:_varchar_pattern_ops
_を使用したf_unaccent(name)
。私の質問は、lower
関数とunaccent
関数を組み合わせたインデックスがfull_text_search lower(f_unaccent(name))
によってトリガーされることです。
lower
関数が全文検索アルゴリズムの処理に役立つかどうかはわかりません。
まず、いくつかのことを明確にする必要があります。
このタイプのクエリは、varchar/text pattern_ops、
_foo LIKE 'bar%'
_
のクエリアンカーされていない検索パターン reqire trigram
。
_foo LIKE '%bar%'
_
インデックス内にあるクエリと同じシーケンスを維持する限り、どちらも関数式で機能します。
全文検索 は、まったく異なるものです。これは、ルートワードへのスタブ、小文字、ストップワードの削除、およびその他の多くのトリックによって、テキストを語彙素に変換します。読み続けます:
残念ながらunaccent
は「不変」ではなく「安定」にすぎません。したがって、unaccent(text)
でインデックスを作成しようとすると、_functions in index expression must be marked IMMUTABLE
_というエラーが発生します。これが、ラッパー_f_accent
_を作成した理由だと思います。 ErwinsがStack Overflow で答えを見つけたからです。こんな感じ
_CREATE EXTENSION unaccent;
CREATE OR REPLACE FUNCTION f_unaccent(text)
RETURNS text AS
$func$
SELECT public.unaccent('public.unaccent', $1) -- schema-qualify function and dictionary
$func$
LANGUAGE sql
IMMUTABLE;
CREATE TABLE foo AS
SELECT 'asdf'::text AS mytext;
CREATE INDEX ON foo (lower(f_unaccent(mytext)) text_pattern_ops);
_
または、トライグラムの場合、
_CREATE INDEX ON foo
USING gin(lower(f_unaccent(mytext)) gin_trgm_ops);
_
ここで、長いシーケンスlower(f_unaccent(mytext))
を実行して機能させる必要があることを思い出してください。
_SELECT *
FROM foo
WHERE lower(f_unaccent(mytext)) LIKE '%whatever%';
_
その方法の代わりに、unaccent
を使用してFTSを使用する辞書を作成します。カスタム辞書を使用すると、必要な処理が実行されます。 FTSは単語をトークンに変換するため、検索が非常に簡単かつ高速になります。
_CREATE EXTENSION unaccent; -- still required it plugs into FTS.
CREATE TEXT SEARCH CONFIGURATION mydict ( COPY = simple );
ALTER TEXT SEARCH CONFIGURATION mydict
ALTER MAPPING FOR hword, hword_part, Word
WITH unaccent, simple;
_
今、あなたはできるはずです
varchar_pattern_ops
_またはtrigram
インデックスを削除する必要に応じて、tsvectorに GistまたはGINインデックスを作成します
_CREATE INDEX ON foo USING to_tsvector('mydict', mytext);
_
トークンとここで何が行われているのかを確認できます。
_select to_tsvector(
'mydict',
'Zoë and Renée are elected to the council of Cheese Eating Surrender Monkeys'
);
to_tsvector
-------------------------------------------------------------------------------------------------------------------------------------
'and':2 'are':4 'cheese':10 'council':8 'eating':11 'elected':5 'monkeys':13 'of':9 'renee':3 'surrender':12 'the':7 'to':6 'zoe':1
(1 row)
_
そして、あなたはこのように単純にテーブルをクエリすることができます、
_SELECT *
FROM foo
WHERE to_tsvector('mydict', mytext) @@ 'cheese & council';
_
simple
を使用する必要もありません。列に1つの言語のステートメントのみが含まれている場合、 他の辞書のいずれか を使用して、物事を簡略化し、ストップワードを削除できます。