アプリに検索を追加する方法:シンプルなフィルターから全文検索まで
アプリに検索を追加するには、まず、うまく動くいちばん単純な方法から始めてください。検索ボックスを置き、それがサーバーのルートを呼び出すようにします。そのルートでは、クエリをいくつかの列と照合してデータベースの行を絞り込み、カテゴリーや価格などの絞り込みも加えます。それでは不十分な場合、例えば関連度によるランキング、単語の語幹処理、大量のレコードが必要になった場合は、データベースの全文検索に切り替えます。ホスト型の検索エンジンに移行するのは、強力なタイプミス許容や、大規模なデータでの即時の結果が必要な場合だけにしてください。どの方法を選んでも、検索は権限を守る必要があります。利用者は、見る権限がないレコードを決して見つけられてはいけません。
アプリにとっての「検索」とは
検索はいくつかの異なるものを含み、ほとんどのアプリは複数を必要とします。
- キーワード検索: テキストボックス。例:「『garden』を含む掲載情報を探す」
- 絞り込み: カテゴリー、都市、価格帯、日付、ステータスなどの構造化された選択。
- 並べ替え: 新着順、安い順、関連度順。
- オートコンプリート: 入力中に表示される候補。
- タイプミスへの許容: 「restuarant」でも「restaurant」が見つかる。
ディレクトリ、求人ボード、ストアでは、テキストボックスより絞り込みのほうが重要なことがよくあります。ツールを選ぶ前に、これらのうちどれが本当に必要かを決めてください。
選択肢
| 方法 | 仕組み | 向いている用途 | 制限 |
|---|---|---|---|
| ブラウザでの絞り込み | リストを読み込み、JavaScriptで絞り込む | 小さな公開リスト(数百件程度) | すべてのデータがすべての訪問者に送られる。件数が多いと遅い |
| データベースのパターン一致 | 「名前にテキストを含む」を大文字小文字を区別せずにサーバーで検索する | 小〜中規模のアプリや管理ツール | ランキングがない。大きなテーブルでは遅くなる場合がある。語幹処理がない |
| データベースの全文検索 | PostgreSQLが単語にインデックスを付け、一致をランク付けする | コンテンツが多いアプリのほとんど | あいまい一致を追加しない限り、タイプミスに弱い |
| あいまい一致(トライグラム) | PostgreSQLが文字の並びの類似度を比較する | 名前、短い項目、タイプミスへの許容 | 拡張機能とインデックスが必要で、調整に手間がかかる |
| ホスト型の検索エンジン | 別のサービスがデータにインデックスを付ける(Algolia、Meilisearch、Typesense、Elasticsearchなど) | 大規模なカタログ、即時検索、強力なタイプミス許容 | 同期を保つ、費用を払う、安全に管理する必要があるもう1つのサービス |
データがすでにPostgreSQLにある場合、その組み込みの全文検索は、実用的な中間の選択肢です。テキストを単語に分け、語幹に還元し(「running」が「run」に一致する)、よくある単語を無視し、一致の度合いで結果をランク付けできます。適切なインデックスがあれば、大きなテーブルでも速さを保てます。
プロンプトの例
シンプルな開始:
掲載情報ページに検索ボックスと絞り込みを追加してください。検索はタイトルと説明に対して、大文字小文字を区別せずに行います。絞り込みは、カテゴリー(ドロップダウン)、都市(ドロップダウン)、最高価格です。検索はサーバーで行い、ページ分割されたAPIルートを使って、1ページあたり20件を返してください。検索と絞り込みの状態はURLに保持し、結果を共有でき、戻るボタンが機能するようにしてください。何も一致しない場合は、わかりやすい空の状態を表示してください。
全文検索へのアップグレード:
掲載情報の検索を、タイトル(重みを高くする)と説明に対するPostgreSQLの全文検索に切り替えてください。適切なインデックスを追加し、関連度で結果をランク付けしてください。既存の絞り込みとページ分割は維持してください。既存のデータは変更しないでください。
名前のタイプミスへの対応:
事業者名であいまい一致を追加し、小さなタイプミスでも結果が見つかるようにしてください。利用できる場合はトライグラムの類似度を使い、インデックスを付けてください。利用できない場合は、現在の検索に戻るようにしてください。
ステップごとの進め方
- 利用者が何を検索するかを一覧にします。 どのフィールド(タイトル、説明、タグ、名前)か?どの絞り込みか?可能であれば、実際の利用者に何人か聞いてください。
- サーバー側から始めます。 クエリと絞り込みを受け取り、結果を1ページ分だけ返すAPIルートを追加します。すべてをブラウザに読み込まないでください。
- クエリに権限を適用します。 利用者が自分のレコードだけ、または公開済みのレコードだけを見られるなら、その条件は検索と同じクエリに入れてください。
- 最初からページ分割を追加します。 ページ番号か「さらに読み込む」のどちらかです。
- 検索の状態をURLに入れます(例:
?q=garden&city=leeds)。共有できるリンクになり、戻るボタンも機能し、絞り込まれたページを検索エンジンにクロールさせることもできます(望む場合)。 - 入力中の検索はデバウンスします。 入力が止まってから数百ミリ秒待ってから検索し、キーストロークごとにリクエストを送らないようにします。
- 検索と絞り込みに使う列がわかったら、インデックスを追加します。
- アップグレードは段階的に。 全文検索、次にあいまい一致、最後にホスト型エンジンへ。単純な段階が実際の利用者の役に立たなくなったときだけ移行します。
- 現実に近いデータでテストします。 数百から数千行、特殊な文字、空のクエリ、非常に長いクエリ、サポートしている場合は他言語も含めてください。
よくある間違い
- テーブル全体をブラウザに読み込む。 50件なら問題ありませんが、5万件では耐えられず、利用者が見てはいけないレコードも含めてすべてが露出します。
- 権限を無視した検索。 検索は一般的な情報漏えいの原因です。検索クエリが「自分のものだけ」「公開済みだけ」という条件を忘れると、非公開の下書きが表示されてしまいます。
- ユーザー入力からSQLを組み立てる。 必ずパラメーター化されたクエリを使ってください。AIビルダーは通常そうしますが、文字列が連結されていないか確認してください。
- 空の状態がない。 「結果がありません」に、候補(絞り込みを解除する、綴りを確認する)を添えると、利用者の離脱を防げます。
- インデックスがない。 テストデータでは検索が問題なく動きますが、実際のデータが増えると遅くなります。
- いきなり検索サービスに飛びつく。 データの2つ目のコピーを同期し、削除を扱い、別のキーのセットも安全に管理しなければなりません。しかも、目に見える効果がないことも多いのです。
- モバイルを忘れる。 絞り込みはスマートフォンの画面に収まる必要があります。サイドバーより、絞り込みのドロワーや折りたたみパネルの方がうまくいくことが多いです。
チェックリスト
- 検索されるフィールドと、存在する絞り込みを把握している
- 検索はサーバーで行われ、ページ分割された結果を返す
- クエリが、アプリの他の部分と同じ権限を強制している
- ユーザー入力はパラメーターとして渡され、SQLに連結されていない
- 検索の状態はURLに保持されている
- 入力はデバウンスされている
- 検索・絞り込みに使う列にインデックスがある
- 空、結果なし、エラーの各状態がわかりやすい
- 現実的なデータ量と、乱れた入力でテストした
Mythexでの検索の追加
Mythexで構築したアプリでは、データは通常、プロジェクト自身のPostgresデータベースに保存されます。そのため、上記のプロンプトから始められます。まずはパターン一致、ランキングが必要になったらPostgreSQLの全文検索です。ホスト型の検索エンジンを使いたい場合は、ご自身のアカウントとキーを用意し、それをプロジェクトのシークレットとして保存します。そして、任意のAPIを連携するで説明されているように、サーバー側からインデックスの作成と検索をするよう、エージェントに依頼してください。
検索は多くのアプリの中核です。アプリの他の部分にどう組み込むかは、ディレクトリサイトの作り方、求人ボードの作り方、マーケットプレイスの作り方を参照してください。
よくある質問
アプリに検索を追加する最も簡単な方法は何ですか?
データがデータベースにある場合は、いくつかの列に対して大文字小文字を区別しない一致でフィルターするサーバーのルートを作るのが、最も簡単な出発点です。ブラウザにすでに読み込まれている小さなリストであれば、ブラウザ内でフィルターするのがさらに簡単です。
検索にAlgoliaやElasticsearchは必要ですか?
最初は通常必要ありません。PostgreSQLの全文検索で、単語の一致、ランキング、数千から数百万行の検索は十分にこなせます。ホスト型の検索エンジンが価値を発揮するのは、強力なタイプミス許容、大量のデータで入力中に即座に結果が出ること、高度な関連度の調整が必要になったときです。
タイプミスがあると、検索で結果が見つからないのはなぜですか?
基本的な一致や標準の全文検索は、入力された単語(またはその語幹)そのものを探すため、誤字があると一致しません。あいまい一致が必要です。例えば、PostgreSQLのトライグラム類似度や、タイプミスに強い検索エンジンを使います。
検索はブラウザで行うべきか、サーバーで行うべきか?
小さな公開リストを超えるものであれば、サーバーで行ってください。サーバー側の検索はスケールし、権限を尊重し、データセット全体をすべての訪問者に送ることもありません。