【実務・中級編】 to_tsquery関数 – PostgreSQL

全文検索の「沼」を避けるために:PostgreSQLの `to_tsquery` を使いこなそう

現場でPostgreSQLを触っていると、「そろそろLIKE検索の性能限界が……」という壁にぶつかることが一度はあるよね。そんな時、多くのエンジニアがたどり着くのがPostgreSQL標準の全文検索機能だ。

中でも肝となるのが `to_tsquery` 関数。これ、ただの「検索文字列を変換するやつ」だと思って適当に使うと、あとで必ず痛い目を見る。今日は、実務でハマりやすいポイントと、現場でちゃんと結果を出すための「作法」について少し話をしようと思う。

—

なぜ `to_tsquery` が必要なのか?

まず前提の整理から。PostgreSQLで全文検索をするには、文字列を `tsvector`(検索用のデータ構造)に変換して保存し、検索時にはクエリを `tsquery`(検索条件)に変換してマッチングさせる必要がある。

`to_tsquery` は、「人間が入力した適当な検索語句を、データベースが解釈可能な論理演算子(AND/OR/NOT)付きの形式に変換する」という役割を担っているんだ。

例えば、こんなクエリを打つとしよう。

SELECT to_tsquery(‘english’, ‘PostgreSQL & Database’);
— 結果: ‘postgresql’ & ‘databas’

見ての通り、単語が正規化(語幹抽出)されて、AND演算子で結ばれた形式になる。これのおかげで、インデックスをフル活用した爆速検索が可能になるわけだ。

実務で一番ハマる「構文エラー」問題

さて、ここからが本題だ。 `to_tsquery` を使っていて一番多いトラブルが、「ユーザーが入力した文字列に記号が含まれていて、SQLがエラーを吐く」というもの。

例えば、ユーザーが検索窓に `(PostgreSQL)` と入力したとする。括弧は `tsquery` の特殊記号だから、そのまま `to_tsquery` に放り込むと、構文エラーで落ちてしまうんだ。

これを防ぐために、実務では `plainto_tsquery` を使うのが「大人の嗜み」だよ。

— これだとエラーになる場合がある
SELECT to_tsquery(‘english’, ‘PostgreSQL & (Database)’);

— こっちなら、記号を単なる単語として解釈してくれる
SELECT plainto_tsquery(‘english’, ‘PostgreSQL & (Database)’);

`plainto_tsquery` は、入力された文字列を「ただの単語の並び」として扱い、自動的にAND検索に変換してくれる。ユーザーの入力に対して厳密なクエリを要求しないなら、こっちの方が圧倒的に安全で、運用も楽だね。

もっと柔軟にやりたいなら `websearch_to_tsquery`

もし君が、「Google検索みたいに、ユーザーが `””` で囲んだらフレーズ検索にしたいし、`-` を入れたら除外検索にしたい」というリクエストを受けたなら、`websearch_to_tsquery` を選ぶべきだ。

— “Postgresql” でフレーズ検索、-Oracle で除外
SELECT websearch_to_tsquery(‘english’, ‘”PostgreSQL” -Oracle’);

これは非常に現代的で、ユーザーの直感に寄り添った検索ができる。最近のアプリ開発なら、まずこれを検討するのが定石かな。

最後に一つだけ、先輩からのアドバイス

`to_tsquery` を使う時は、必ず 「どの言語設定(辞書)を使うか」 を意識してほしい。

日本語の検索なら `japanese` 辞書(pg_bigmなどの拡張機能が必要になることが多いけど)を使うし、英語なら `english` を使う。ここがズレていると、語幹の処理(Running → Run など)がうまくいかず、「検索してもヒットしない」という悲劇が起きる。

まずは `to_tsquery(‘english’, ‘running’)` を実行して、どんな結果になるか確認してみてほしい。`’run’` と出てくるはずだ。この「データベースがどう解釈しているか」を理解できれば、全文検索の設計はもう怖くないはずだよ。

全文検索は沼が深そうに見えて、PostgreSQLの標準機能を正しく使えば非常に強力な武器になる。ぜひ、次のプロジェクトで試してみてくれ。また何か詰まったら、いつでも聞きに来るといい。

コメント

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