Laravel Scout × MeiliSearch:高性能検索を実現するための完全
はじめに
現代の検索体験は単なる文字列一致だけでは不十分です。ユーザーは次のような高度な検索を期待しています:
- 即時レスポンスの高速検索
- タイポ(誤字)に強い検索
- 複数フィールドに跨る検索
- コンテキストを考慮したランキング
- 柔軟なフィルターやソート
Laravel では Laravel Scout + MeiliSearch を組み合わせることで、これらを驚くほど簡単に実現できます。本記事は単なるインストール手順ではありません。より深く、実践的で、エンジニアが現場で役立つ知識をまとめています。
この記事では以下を詳しく解説します:
- Scout の内部動作とアーキテクチャ
- 高度な indexing(searchable array の設計)
- MeiliSearch ranking rule の理解
- 複数モデルへの検索(Federated Search)
- オートコンプリートやサジェスト
- 大規模データのインデックス最適化
- パフォーマンス最適化のベストプラクティス
I. Laravel Scout の仕組み
1. 基本ワークフロー
Laravel Scout は「Eloquent モデルの変更 → Search Index に反映」という仕組みで動作します。
モデルが作成された時
MeiliSearch に新しい document を追加。
更新された時
対応する document を更新。
削除された時
document を削除。
scout:import を実行した時
php artisan scout:import "App\Models\Product"
Scout は:
- データベースを chunk 単位で取得
-
toSearchableArray()を変換 - MeiliSearch に bulk import
2. Queue ベースの indexing
SCOUT_QUEUE=true
キューを利用すると:
- Web リクエストのレスポンスが早くなる
- 大量データ更新時の負荷を削減
- スケーラビリティが向上
II. MeiliSearch の特徴とアーキテクチャ
MeiliSearch はメモリ最適化された高速全文検索エンジンで、index を RAM+disk snapshot に保持するためレスポンスが非常に高速です。
主な特徴
- 高速な全文検索
- Fuzzy Search(誤字に強い)
- タイポ tolerance
- Ranking Rules による高度な検索結果制御
- 多フィールド検索
- 使いやすい API
- 軽量でデプロイが簡単
重要な概念
1. Document
モデル 1 件 = Document 1 件
2. Index
Document の集合。
例:products, users, blog_posts
3. Ranking Rules
デフォルトは:
- typo
- words
- proximity
- attribute
- exactness
MeiliSearch の検索クオリティが高い理由の核心部分です。
III. Laravel 側の高度な設定
1. Index するフィールドを最適化
全フィールドを index すると遅くなります。必要なものだけに絞りましょう。
public function toSearchableArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'brand' => $this->brand->name ?? null,
'price' => $this->price,
'tags' => $this->tags->pluck('name')->toArray(),
];
}
2. Transformer 精度向上
検索できるように正規化(Normalize)するべき場合があります。
- HTML の除去
- Lowercase
- Unicode normalize
- 絵文字の正規化
public function toSearchableArray()
{
$array = $this->only(['title']);
$array['content'] = strip_tags($this->content);
return $array;
}
IV. 高度な検索機能
1. Ranking Rules のカスタマイズ
Elasticsearch の boosting と違い、MeiliSearch は ranking rules を調整します。
{
"rankingRules": [
"typo",
"words",
"proximity",
"attribute:priority DESC",
"exactness"
]
}
2. Filter の組み合わせ
Product::search('iphone')
->where('price', '>', 100000)
->where('brand', 'Apple')
->get();
V. 複数モデル検索(Federated Search)
Scout は multi-model search を直接サポートしませんが、自作は簡単です。
$results = [
'products' => Product::search($keyword)->take(5)->get(),
'blogs' => Blog::search($keyword)->take(5)->get(),
'users' => User::search($keyword)->take(5)->get(),
];
または Unified Index を作成する方法もあります:
public function searchableAs()
{
return 'global_index';
}
Document 例:
return [
'type' => 'product',
'title' => $this->name,
'description' => $this->description,
];
VI. オートコンプリートとサジェスト
MeiliSearch は prefix search に強いので、以下だけで autocomplete が実現できます。
Product::search($keyword)->take(7)->get();
Prefix を有効にする場合:
Product::search($keyword, function ($engine, $query, $options) {
$options['prefix'] = true;
return $engine->search($query, $options);
});
VII. 大規模データ向け高速化テクニック
最適化 1: Queue indexing
SCOUT_QUEUE=true
最適化 2: 大量 import 時は auto-sync をオフ
Product::withoutSyncingToSearch(function () {
// 大量 insert
});
最適化 3: 再インポート前に index を flush
php artisan scout:flush "App\Models\Product"
最適化 4: Index field を絞る
検索速度に直結。
VIII. 他エンジンとの比較
| 比較項目 | MeiliSearch | Elasticsearch | MySQL/Postgres |
|---|---|---|---|
| 検索速度 | 高速 | 非常に高速 | 普通 |
| 機能 | 充実 | 非常に強力 | 基本的 |
| 導入容易性 | 〇 | △(学習コスト大) | 〇 |
| RAM 消費 | 少 | 多 | 少 |
| 大規模データ | 強い | 最強 | 弱い |
通常の Web アプリであれば MeiliSearch が最適なバランス を持っています。
IX. Search Controller の実装例
public function search(Request $request)
{
$keyword = $request->input('q');
$products = Product::search($keyword)->paginate(15);
return view('search.results', compact('products', 'keyword'));
}
まとめ
Laravel Scout + MeiliSearch は、以下の特徴を持つ優れた全文検索基盤です:
- 高速で正確
- Fuzzy search や prefix search をサポート
- モダンで使いやすい ranking rules
- 拡張性が高く、複雑な search UI にも対応可能
- 大規模データにも耐えられる
Laravel プロジェクトに "本格的な検索" が必要なら、最初に検討すべき選択肢です。
参考資料
- Laravel Scout: https://github.com/laravel/scout
- MeiliSearch 公式ドキュメント: https://www.meilisearch.com/docs
- MeiliSearch Ranking Rules 解説: https://www.meilisearch.com/docs/learn/core_concepts/relevancy
- Laravel Scout x MeiliSearch チュートリアル: https://laravel-news.com/laravel-scout-meilisearch