メインコンテンツへスキップ

はじめに

アプリケーションに検索機能を追加する方法は用途に応じて複数あります。Laravelはキーワード一致から AI を使ったセマンティック検索まで、外部サービス不要で対応できる組み込みツールを提供しています。

機能比較

機能外部サービス特徴
whereFullText不要MariaDB / MySQL / PostgreSQL 組み込みの全文インデックス
whereVectorSimilarTo不要(PostgreSQL + pgvector)意味的な類似度で検索。AI SDKが必要
RerankingAI プロバイダー任意の結果セットを AI で関連度順に並び替え
Laravel Scout不要(database エンジン)/ 任意Eloquent モデルの自動インデックス同期

全文検索

LIKE クエリはシンプルな部分一致には便利ですが、言語を理解しません。全文検索は専用インデックスを使って単語の境界・語形変化・関連度スコアを考慮した検索を行います。 MariaDB・MySQL・PostgreSQL は全文検索を組み込みでサポートしており、外部サービスは不要です。
全文検索は MariaDB・MySQL・PostgreSQL でサポートされています。

全文インデックスの追加

全文検索を使うには、まず対象カラムに全文インデックスを追加します。
Schema::create('articles', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->timestamps();

    $table->fullText(['title', 'body']); // 複合インデックス
});
PostgreSQL ではインデックスに言語設定を指定できます。英語以外の言語では語形変化の処理が変わります。
$table->fullText('body')->language('english');
インデックスの詳細はマイグレーションを参照してください。
日本語全文検索の注意事項
MySQL での日本語全文検索はやや使いにくい面があります。AWS RDS では N-gram パーサーのみ利用可能で、形態素解析プラグイン(MeCab)を追加できないため制限されます。Laravel Cloud の MySQL も同様と考えられます。PostgreSQL でも日本語の語形変化対応は限定的です。日本語検索の精度が重要な場合は Meilisearch や Typesense などの専用エンジンの利用を検討してください。

全文クエリの実行

インデックスを追加したら whereFullText メソッドで検索します。Laravel は使用しているデータベースドライバーに合わせて適切な SQL を生成します(MariaDB / MySQL では MATCH(...) AGAINST(...)、PostgreSQL では to_tsvector(...) @@ plainto_tsquery(...))。
$articles = Article::whereFullText('body', 'web developer')->get();
複合インデックスを作成した場合は、同じカラム配列を渡します。
$articles = Article::whereFullText(
    ['title', 'body'], 'web developer'
)->get();
MariaDB・MySQL では結果が自動的に関連度スコア順に並びます。PostgreSQL では whereFullText はマッチするレコードをフィルタリングするだけで関連度順にはなりません。PostgreSQL で自動的な関連度順が必要な場合は Scout のデータベースエンジン が有効です。
orWhereFullText メソッドで OR 条件として全文検索を追加することもできます。詳細はクエリビルダードキュメントを参照してください。

セマンティック / ベクター検索

全文検索はキーワードの一致に依存しています。ベクター検索は根本的に異なるアプローチで、AI が生成したベクター埋め込みを使ってテキストの意味を数値配列として表現し、意味的に近い結果を検索します。 たとえば「best wineries in Napa Valley」という検索で「Top Vineyards to Visit」というタイトルの記事がヒットします。単語は一致しなくても意味が近いからです。
ベクター検索には Laravel AI SDK が必要で、PostgreSQL(pgvector 拡張が必要)と MongoDB(Laravel MongoDB パッケージが必要)をサポートしています。Laravel Cloud のすべての Postgres データベースには pgvector が事前にインストールされています。

埋め込みの生成

埋め込みはテキストの意味を表す高次元の数値配列(通常数百〜数千次元)です。Laravel の Stringable クラスの toEmbeddings メソッドで生成できます。
use Illuminate\Support\Str;

$embedding = Str::of('Napa Valley has great wine.')->toEmbeddings();
複数のテキストを一度に処理する場合は Embeddings クラスを使うと効率的です(API 呼び出しが 1 回で済みます)。
use Laravel\Ai\Embeddings;

$response = Embeddings::for([
    'Napa Valley has great wine.',
    'Laravel is a PHP framework.',
])->generate();

$response->embeddings; // [[0.123, 0.456, ...], [0.789, 0.012, ...]]
埋め込みプロバイダーの設定や次元数のカスタマイズについては AI SDK ドキュメントを参照してください。

ベクターの保存とインデックス作成

ベクター埋め込みを保存するには、マイグレーションで vector カラムを定義します。埋め込みプロバイダーの出力次元数に合わせて dimensions を指定してください(例:OpenAI の text-embedding-3-small は 1536 次元)。index() を呼び出して HNSW インデックスを作成すると、大規模データセットでの類似検索が大幅に高速化されます。
Schema::ensureVectorExtensionExists(); // pgvector 拡張を有効化

Schema::create('documents', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->vector('embedding', dimensions: 1536)->index();
    $table->timestamps();
});
Eloquent モデルでは embedding カラムを array にキャストして、PHP 配列とデータベースのベクター形式の変換を自動化します。
protected function casts(): array
{
    return [
        'embedding' => 'array',
    ];
}
ベクターカラムとインデックスの詳細はマイグレーションを参照してください。

類似度による検索

埋め込みを保存したら、whereVectorSimilarTo メソッドで類似レコードを検索できます。コサイン類似度でベクターを比較し、minSimilarity 閾値以下の結果をフィルタリングして、関連性の高い順に自動ソートします。閾値は 0.01.0 の値で、1.0 は完全一致を意味します。
$documents = Document::query()
    ->whereVectorSimilarTo('embedding', $queryEmbedding, minSimilarity: 0.4)
    ->limit(10)
    ->get();
埋め込み配列の代わりに文字列を渡すと、Laravel が自動的に埋め込みを生成してくれます。ユーザーの検索クエリをそのまま渡せるのでとても便利です。
$documents = Document::query()
    ->whereVectorSimilarTo('embedding', 'best wineries in Napa Valley')
    ->limit(10)
    ->get();
より細かい制御が必要な場合は whereVectorDistanceLessThanselectVectorDistanceorderByVectorDistance も利用できます。詳細はクエリビルダードキュメントAI SDK ドキュメントを参照してください。

リランキング

リランキングは、AI モデルが結果セットをクエリとの関連度順に並び替える手法です。ベクター検索と異なり、事前に埋め込みを計算・保存する必要はなく、任意のテキストコレクションに適用できます。 全文検索で大量のレコードを素早く絞り込んだ後にリランキングを適用する「検索→リランク」パターンが特に効果的です。データベースの速さと AI の精度を両立できます。
use Laravel\Ai\Reranking;

$response = Reranking::of([
    'Django is a Python web framework.',
    'Laravel is a PHP web application framework.',
    'React is a JavaScript library for building user interfaces.',
])->rerank('PHP frameworks');

$response->first()->document; // "Laravel is a PHP web application framework."
Laravel コレクションには rerank マクロがあり、フィールド名(またはクロージャ)とクエリを渡すだけで Eloquent の結果をリランクできます。
$articles = Article::all()
    ->rerank('body', 'Laravel tutorials');
リランキングプロバイダーの設定と利用可能なオプションについては AI SDK ドキュメントを参照してください。

Laravel Scout

ここまで説明した検索手法はすべてクエリビルダーのメソッドを直接呼び出すものでした。Laravel Scout は別アプローチを取ります。Eloquent モデルに Searchable トレイトを追加すると、Scout がレコードの作成・更新・削除に合わせて検索インデックスを自動同期します。

データベースエンジン

Scout 組み込みのデータベースエンジンは既存のデータベースに対して全文検索と LIKE 検索を行います。外部サービスもインフラも追加不要です。 toSearchableArray メソッドで検索対象のカラムを定義します。PHP 属性でカラムごとに検索戦略を指定できます。
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Attributes\SearchUsingFullText;
use Laravel\Scout\Attributes\SearchUsingPrefix;
use Laravel\Scout\Searchable;

class Article extends Model
{
    use Searchable;

    #[SearchUsingPrefix(['id'])]
    #[SearchUsingFullText(['title', 'body'])]
    public function toSearchableArray(): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'body' => $this->body,
        ];
    }
}
属性検索戦略
SearchUsingFullText全文インデックスを使用(MATCH...AGAINST / to_tsvector
SearchUsingPrefix前方一致(example%
なし前後ワイルドカード(%example%
SearchUsingFullText を指定するカラムには事前に全文インデックスが必要です。
トレイトを追加したら、search メソッドでモデルを検索できます。Scout のデータベースエンジンは PostgreSQL でも自動的に関連度順で結果を返します。
$articles = Article::search('Laravel')->get();

サードパーティエンジン

Scout は AlgoliaMeilisearchTypesense などのサードパーティ検索エンジンもサポートします。これらはタイポ許容・ファセット検索・ジオサーチ・カスタムランキングなど高度な機能を提供します。 Scout は統一 API を提供するため、後でデータベースエンジンからサードパーティエンジンに移行する際のコード変更は最小限で済みます。
ほとんどのアプリケーションは外部検索エンジンを必要としません。このページで説明した組み込み手法が大多数のユースケースをカバーします。
Scout の詳細は Laravel Scout ガイドを参照してください。

技術の組み合わせ

ここまで紹介した検索手法は相互に排他的ではありません。組み合わせることで最良の結果が得られます。

全文検索 + リランキング

全文検索で候補を素早く絞り込み、リランキングでセマンティックな関連度順に並び替えます。データベース速度と AI 精度を両立するパターンです。
$articles = Article::query()
    ->whereFullText('body', $request->input('query'))
    ->limit(50)
    ->get()
    ->rerank('body', $request->input('query'), limit: 10);

ベクター検索 + 通常のフィルター

ベクター類似検索と通常の where 句を組み合わせて、特定のサブセットに絞ったセマンティック検索を実現します。チームやカテゴリーで絞り込みながら意味的な検索をしたい場合に便利です。
$documents = Document::query()
    ->where('team_id', $user->team_id)
    ->whereVectorSimilarTo('embedding', $request->input('query'))
    ->limit(10)
    ->get();

関連ページ

Laravel Scout

Searchable トレイトでモデルを自動インデックス同期する完全ガイド。

Laravel AI SDK

ベクター埋め込みとリランキングに必要な AI SDK の設定方法。

クエリビルダー

whereFullText・whereVectorSimilarTo などのクエリビルダーメソッドの詳細。

マイグレーション

全文インデックスとベクターカラムの作成方法。
最終更新日 2026年6月26日