【実務・中級編】 テキスト検索設定と辞書 – PostgreSQL

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は、使い方次第でまだまだ化けます。ぜひ次のリリースで、ちょっとした辞書設定を仕込んでみてください。現場で「おっ、検索使いやすくなったね」と言われる瞬間、エンジニア冥利に尽きますよ。

それでは、また次回の記事でお会いしましょう!

コメント

タイトルとURLをコピーしました