PostgreSQLの全文検索、標準機能だけでどこまで戦えるか?辞書設定を使い倒そう
こんにちは。最近「PostgreSQLの全文検索って、結局どの程度まで作り込めるの?」という質問を後輩から受けました。
外部の検索エンジン(ElasticsearchやAlgoliaなど)を導入するのは確かに一つの正解です。でも、小〜中規模のアプリケーションなら、PostgreSQLの標準機能(`tsvector`と`tsquery`)をしっかりチューニングするだけで、驚くほど高機能な検索が実現できます。
今日は、PostgreSQLの「テキスト検索設定(`ts_config`)」と「辞書」をいじって、実戦レベルの検索体験を作るコツを伝授します。
—
なぜ「標準の検索」が微妙に感じてしまうのか
PostgreSQLのデフォルト設定(`english`など)をそのまま使うと、日本語環境ではまずうまくいきません。単語の区切りが変だったり、助詞が引っかかったり、そもそも「同義語」が無視されたりします。
これを解決するのが、「カスタム辞書」と「検索設定」のカスタマイズです。
—
1. 検索設定(ts_config)の基本を押さえる
まずは「どの辞書を、どの優先順位で使うか」を決めるのが`ts_config`です。
— 現在の設定を確認
SELECT FROM pg_ts_config WHERE cfgname = ‘english’;
— 新しい設定を作成(既存のsimpleをベースにするのがコツ)
CREATE TEXT SEARCH CONFIGURATION public.my_ja_config (COPY = simple);
ここで「simple」をベースにする理由は、余計な正規化(語幹抽出など)を一旦排除して、自分たちの意図した通りに単語を制御しやすくするためです。
—
2. ストップワードでノイズを消す
検索結果に「これ、出てこなくていいだろ」という単語は混ざっていませんか? これがストップワードです。
例えば、「検索」「機能」といった頻出単語をあえて除外したい場合、辞書ファイルを作って読み込ませます。
1. `/usr/share/postgresql/15/tsearch_data/my_stop.txt` に単語を列挙。
2. それを辞書として登録:
CREATE TEXT SEARCH DICTIONARY my_stop_dict (
TEMPLATE = simple,
STOPWORDS = my_stop
);
— 設定に紐付け
ALTER TEXT SEARCH CONFIGURATION my_ja_config
ALTER MAPPING FOR asciiword WITH my_stop_dict, simple;
こうすることで、ユーザーが「検索機能とは」と打っても、「機能」というノイズを無視した検索が可能になります。
—
3. 同義語辞書(thesaurus)が「現場の神」
ここが一番重要です。ビジネスの現場では、「ノートPC」と「ノートパソコン」と「ラップトップ」は同じものを指すべきですよね。これらを検索エンジン側に教え込むのが同義語辞書です。
thesaurus_file の書き方(例:my_synonyms.ths):
ノートパソコン : ノートPC
ラップトップ : ノートPC
MacBook : Apple
これを辞書として定義します。
CREATE TEXT SEARCH DICTIONARY my_syn_dict (
TEMPLATE = thesaurus,
DictFile = my_synonyms,
Dictionary = simple
);
ALTER TEXT SEARCH CONFIGURATION my_ja_config
ALTER MAPPING FOR asciiword WITH my_syn_dict, simple;
これで、ユーザーが「ラップトップ」と検索しても、「ノートPC」がヒットするようになります。これだけでUXは劇的に変わります。
—
4. 運用上のちょっとしたアドバイス
これらを実装する際、いくつか実務的な注意点があります。
- インデックスを忘れずに:
`tsvector`を毎回計算させると重いです。必ず`GIN`インデックスを貼りましょう。
CREATE INDEX idx_fts_content ON my_table USING GIN(to_tsvector(‘my_ja_config’, content));
- 辞書の更新は再起動が不要:
辞書ファイルを書き換えた後は、`ALTER TEXT SEARCH DICTIONARY …` を実行するか、PostgreSQLを再読み込みさせるだけで反映されます。運用コストは意外と低いです。
- 日本語の場合は「分かち書き」が鬼門:
PostgreSQL標準の`to_tsvector`は日本語の形態素解析(MeCabなど)を標準では含んでいません。もし精度を極めるなら、`pg_bigm`のようなバイグラムベースの拡張機能と組み合わせるのが、今の日本の現場では最も「安定して強い」構成になるはずです。
—
最後に:完璧を目指しすぎないこと
データベースエンジニアとして一つだけアドバイスすると、「検索の完璧」を求めすぎると、辞書のメンテナンスが地獄になります。
まずは「ユーザーが最も検索するワード」と「検索してほしいのにヒットしないワード」のトップ10を分析してください。そこを重点的に`thesaurus`でカバーする。これだけで、コストパフォーマンスは最高になります。
PostgreSQLは、使い方次第でまだまだ化けます。ぜひ次のリリースで、ちょっとした辞書設定を仕込んでみてください。現場で「おっ、検索使いやすくなったね」と言われる瞬間、エンジニア冥利に尽きますよ。
それでは、また次回の記事でお会いしましょう!
コメント