イントロダクション
Laravel Scout(Scout、斥候)は、Eloquentモデルへ、シンプルなドライバベースのフルテキストサーチを提供します。モデルオブサーバを使い、Scoutは検索インデックスを自動的にEloquentレコードと同期します。
現在、ScoutはAlgolia, MeiliSearch, MySQL/PostgreSQL
(database
)
ドライバを用意しています。さらに、Scoutはローカル開発用途に設計された、外部依存やサードパーティサービスを必要としない「コレクション」ドライバも用意しています。加えて、カスタムドライバの作成も簡単で、独自の検索実装でScoutを自由に拡張可能です。
インストール
最初に、Composerパッケージマネージャを使い、Scoutをインストールします。
composer require laravel/scout
Scoutをインストールした後、vendor:publish
Artisanコマンドを実行してScout設定ファイルをリソース公開する必要があります。このコマンドは、scout.php
設定ファイルをアプリケーションのconfig
ディレクトリへリソース公開します。
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
最後に、検索可能にしたいモデルにLaravel\Scout\Searchable
トレイトを追加します。このトレイトは、モデルを検索ドライバと自動的に同期させるモデルオブザーバを登録します。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
}
ドライバの事前要件
Algolia
Algoliaドライバを使用する場合、Algolia
id
とsecret
接続情報をconfig/scout.php
設定ファイルで設定する必要があります。接続情報を設定し終えたら、Algolia
PHP
SDKをComposerパッケージマネージャで、インストールする必要があります。
composer require algolia/algoliasearch-client-php
MeiliSearch
MeiliSearchは、非常に高速なオープンソースの検索エンジンです。ローカルマシンにMeiliSearchをインストールする方法がわからない場合は、Laravelの公式サポートのDocker開発環境であるLaravel Sailを利用できます。
Meilisearchドライバを使用する場合は、Composerパッケージマネージャを使用して、MeiliSearch PHP SDKをインストールする必要があります。
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
次に、アプリケーションの.env
ファイル内のSCOUT_DRIVER
環境変数とMeiliSearchhost
とkey
認証情報を設定します。
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey
MeiliSearchの詳細については、MeiliSearchのドキュメントを参照してください。
さらに、MeiliSearchのバイナリ互換のドキュメントを見て、自分が使っているMeiliSearchのバイナリバージョンと互換性のあるバージョンのmeilisearch/meilisearch-php
をインストールしてください。
Warning!! MeiliSearchを利用しているアプリケーションのScoutをアップグレードする際には、常にMeiliSearchサービス自体に追加の破壊的な変更がないか確認する必要があります。
キュー投入
厳密にはScoutを使用する必要はありませんが、ライブラリを使用する前に、キュードライバの設定を強く考慮する必要があります。キューワーカを実行すると、Scoutはモデル情報を検索インデックスに同期するすべての操作をキューに入れることができ、アプリケーションのWebインターフェイスのレスポンス時間が大幅に短縮されます。
キュードライバを設定したら、config/scout.php
設定ファイルのqueue
オプションの値をtrue
に設定します。
'queue' => true,
queue
オプションをfalse
に設定している場合でも、AlgoliaやMeilisearchなど、一部のScoutドライバは常に非同期でレコードをインデックスしていることを覚えておくことが重要です。つまり、Laravelアプリケーション内でインデックス操作が完了しても、検索エンジン自体には新しいレコードや更新されたレコードがすぐに反映されない可能性があります。
Scoutジョブで利用する接続とキューを指定するには、queue
設定オプションを配列として定義します。
'queue' => [
'connection' => 'redis',
'queue' => 'scout'
],
設定
モデルインデックスの設定
各Eloquentモデルは、検索可能レコードすべてを含む、指定された検索「インデックス」と同期されます。言い換えれば、各インデックスはMySQLテーブルのようなものであると、考えられます。デフォルトで、各モデルはそのモデルの典型的な「テーブル」名に一致するインデックスへ保存されます。通常、モデルの複数形ですが、モデルのsearchableAs
メソッドをオーバーライドすることで、このモデルのインデックスを自由にカスタマイズ可能です。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
/**
* モデルに関連付けられているインデックスの名前を取得
*
* @return string
*/
public function searchableAs()
{
return 'posts_index';
}
}
検索可能データの設定
デフォルトでは、指定されたモデルのtoArray
形態全体が、検索インデックスへ保存されます。検索インデックスと同期するデータをカスタマイズしたい場合は、そのモデルのtoSearchableArray
メソッドをオーバーライドできます。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
/**
* モデルのインデックス可能なデータ配列の取得
*
* @return array
*/
public function toSearchableArray()
{
$array = $this->toArray();
// データ配列をカスタマイズ
return $array;
}
}
MeiliSearchなどの検索エンジンでは、正しい型のデータに対してのみフィルタリング操作(>
、<
など)が行われます。したがって、これらの検索エンジンを使用して検索可能なデータをカスタマイズする場合は、数値を確実に正しい型にキャストする必要があります。
public function toSearchableArray()
{
return [
'id' => (int) $this->id,
'name' => $this->name,
'price' => (float) $this->price,
];
}
Filterableデータとインデックス(MeiliSearch)の設定
Scoutの他のドライバと異なり、MeiliSearchでは、フィルタリング可能な属性(Filterable)、ソート可能な属性(Sortable)やその他サポートされている設定フィールドなどのインデックス検索設定を事前に定義しておく必要があります。
フィルタリング可能な属性とは、Scoutのwhere
メソッドを呼び出す際にフィルタリングする予定の属性であり、ソート可能な属性とは、ScoutのorderBy
メソッドを呼び出す際にソートする予定の属性のことです。インデックスの設定を行うには、アプリケーションのscout
設定ファイルにある、meilisearch
設定項目のindex-settings
部分を調整します。
use App\Models\User;
use App\Models\Flight;
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY', null),
'index-settings' => [
User::class => [
'filterableAttributes'=> ['id', 'name', 'email'],
'sortableAttributes' => ['created_at'],
// その他の設定項目…
],
Flight::class => [
'filterableAttributes'=> ['id', 'destination'],
'sortableAttributes' => ['updated_at'],
],
],
],
インデックスの基盤となるモデルがソフトデリート可能で、かつindex-settings
配列に含まれていれば、Scoutは自動的にそのインデックスのソフトデリートモデルに対するフィルタリングをサポートします。もし、ソフトデリート可能なモデルのインデックスに対して定義すべきフィルタリングやソート可能な属性がなければ、そのモデルに対し、index-settings
配列へ空のエントリを追加するだけでよいでしょう。
'index-settings' => [
Flight::class => []
],
アプリケーションのインデックス設定後に、scout:sync-index-settings
Artisanコマンドを呼び出す必要があります。このコマンドは、現在設定しているインデックス設定をMeiliSearchに通知します。このコマンドをデプロイプロセスの一部とすると便利です。
php artisan scout:sync-index-settings
モデルIDの設定
デフォルトでは、Scoutはモデルの主キーを、検索インデックスに保存されているモデルの一意のID/キーとして使用します。この動作をカスタマイズする必要がある場合は、モデルのgetScoutKey
メソッドとgetScoutKeyName
メソッドをオーバーライドできます。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class User extends Model
{
use Searchable;
/**
* モデルのインデックスに使用する値の取得
*
* @return mixed
*/
public function getScoutKey()
{
return $this->email;
}
/**
* モデルのインデックスに使用するキー名の取得
*
* @return mixed
*/
public function getScoutKeyName()
{
return 'email';
}
}
モデルごとのサーチエンジン設定
検索時、Scoutはアプリケーションのscout
設定ファイルで指定したデフォルト検索エンジンを通常使用します。しかし、特定モデルの検索エンジンを変更したい場合は、そのモデルのsearchableUsing
メソッドをオーバーライドしてください。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\EngineManager;
use Laravel\Scout\Searchable;
class User extends Model
{
use Searchable;
/**
* Get the engine used to index the model.
*
* @return \Laravel\Scout\Engines\Engine
*/
public function searchableUsing()
{
return app(EngineManager::class)->engine('meilisearch');
}
}
ユーザーの識別
Scoutを使用すると、Algoliaを使用するときにユーザーを自動識別することもできます。認証済みユーザーを検索操作に関連付けると、Algoliaのダッシュボード内で検索分析を表示するときに役立つ場合があります。アプリケーションの.env
ファイルでSCOUT_IDENTIFY
環境変数をtrue
として定義することにより、ユーザー識別を有効にできます。
SCOUT_IDENTIFY=true
この機能を有効にすると、リクエストのIPアドレスと認証済みユーザーのプライマリ識別子もAlgoliaに渡されるため、これらのデータはそのユーザーが行った検索リクエストへ関連付けられます。
データベース/コレクションエンジン
データベースエンジン
Warning!! 現在、データベースエンジンは、MySQLとPostgreSQLをサポートしています。
中規模のデータベースとやり取りするしたり、作業負荷が軽いアプリケーションでは、Scoutの「データベース」エンジンで始めるのが便利でしょう。データベースエンジンは、既存のデータベースから結果をフィルタリングする際に、「where like」句と全文インデックスを使用して、クエリの検索結果を決定します。
データベースエンジンを使うには、SCOUT_DRIVER
環境変数の値をdatabase
に設定するか、アプリケーションのscout
設定ファイルに直接database
ドライバを指定してください。
SCOUT_DRIVER=database
データベースエンジンを好みのドライバに指定したら、検索可能なデータの設定を行う必要があります。次に、モデルに対して検索クエリの実行を開始します。データベースエンジンを使用する場合、AlgoliaやMeiliSearchのように、検索エンジンのインデックス作成は必要ありません。
データベース検索戦略のカスタマイズ
デフォルトでは、データベースエンジンは、検索可能として設定したすべてのモデル属性に対して、"WHERE
LIKE"クエリを実行します。しかし、この方法では状況により、パフォーマンス低下を招くことがあります。そこで、データベースエンジンの検索戦略を設定することで、指定した一部のカラムでは全文検索クエリを利用し、あるいは文字列全体を検索(%example%
)するのではなく、前方一致で検索する(example%
)"WHERE
LIKE"制約のみを利用できます。
こうした振る舞いを定義するには、モデルのtoSearchableArray
メソッドでPHP属性を割り付けてください。追加の検索戦略動作を割り当てていないカラムには、デフォルトの"WHERE
LIKE"戦略を使い続けます。
use Laravel\Scout\Attributes\SearchUsingFullText;
use Laravel\Scout\Attributes\SearchUsingPrefix;
/**
* モデルに対するインデックス可能なデータの配列を取得
*
* @return array
*/
#[SearchUsingPrefix(['id', 'email'])]
#[SearchUsingFullText(['bio'])]
public function toSearchableArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'bio' => $this->bio,
];
}
Warning!! あるカラムへ、フルテキストクエリ制約の使用を指定する前に、そのカラムにフルテキストインデックスを割り当て済みであることを確認してください。
コレクションエンジン
ローカル開発時には、AlgoliaやMeiliSearchの検索エンジンを自由に使用することができますが、「コレクション(collection)」エンジンでスタートした方が便利な場合もあります。コレクション・エンジンは、既存データベースからの結果に対して、"where"節とコレクション・フィルタリングを用いて、クエリに該当する検索結果を決定します。このエンジンを使用する場合、Searchableモデルをインデックス化する必要はなく、シンプルにローカル・データベースから検索します。
コレクションエンジンを使用するには,環境変数SCOUT_DRIVER
の値をcollection
に設定するか,アプリケーションのscout
設定ファイルでcollection
ドライバを直接指定します。
SCOUT_DRIVER=collection
コレクションドライバを使用ドライバに指定したら、モデルに対して検索クエリの実行を開始できます。コレクションエンジンを使用する場合、AlgoliaやMeiliSearchのインデックスのシードに必要なインデックス作成などの検索エンジンのインデックス作成は不要です。
データベースエンジンとの違い
一見すると、「データベース」エンジンと「コレクション」エンジンはかなり似ています。どちらも、あなたのデータベースと直接やりとりして、検索結果を取得します。しかし、コレクションエンジンはフルテキストインデックスやLIKE
句を利用して一致レコードを探し出しません。その代わりに、可能性があるすべてのレコードを取得し、LaravelのStr::is
ヘルパを使い、モデルの属性値内に検索文字列が存在しているか判断します。
コレクションエンジンは、Laravelがサポートする(SQLiteやSQL Serverを含む)すべてのリレーショナルデータベースで動作するため、最も使いやすい検索エンジンですが、Scoutのデータベースエンジンに比べると効率は落ちます。
インデックス
バッチ取り込み
Scoutを既存のプロジェクトにインストールする場合は、インデックスへインポートする必要のあるデータベースレコードがすでに存在している可能性があります。Scoutは、既存のすべてのレコードを検索インデックスにインポートするために使用できるscout:import
Artisanコマンドを提供しています。
php artisan scout:import "App\Models\Post"
flush
コマンドは、検索インデックスからモデルの全レコードを削除するために使用します。
php artisan scout:flush "App\Models\Post"
インポートクエリの変更
バッチインポートで全モデルを取得するために使用されるクエリを変更する場合は、モデルにmakeAllSearchableUsing
メソッドを定義してください。これはモデルをインポートする前に、必要になる可能性のあるイエガーリレーションの読み込みを追加するのに最適な場所です。
/**
* 全モデルを検索可能にするときの、モデル取得に使用するクエリを変更
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function makeAllSearchableUsing($query)
{
return $query->with('author');
}
レコード追加
モデルにLaravel\Scout\Searchable
トレイトを追加したら、モデルインスタンスを保存
または作成
するだけで、検索インデックスに自動的に追加されます。キューを使用するようにScoutを設定した場合、この操作はキューワーカによってバックグラウンドで実行されます。
use App\Models\Order;
$order = new Order;
// ...
$order->save();
クエリによるレコード追加
Eloquentクエリを介してモデルのコレクションを検索インデックスに追加する場合は、searchable
メソッドをEloquentクエリにチェーンできます。searchable
メソッドはクエリの結果をチャンクし、レコードを検索インデックスに追加します。繰り返しますが、キューを使用するようにScoutを設定した場合、すべてのチャンクはキューワーカによってバックグラウンドでインポートされます。
use App\Models\Order;
Order::where('price', '>', 100)->searchable();
Eloquentリレーションインスタンスで
searchable
メソッドを呼び出すこともできます。
$user->orders()->searchable();
または、メモリ内にEloquentモデルのコレクションが既にある場合は、コレクションインスタンスでsearchable
メソッドを呼び出して、モデルインスタンスを対応するインデックスに追加できます。
$orders->searchable();
Note:
searchable
メソッドは、「アップサート(upsert)」操作と考えるられます。つまり、モデルレコードがすでにインデックスに含まれている場合は、更新され、検索インデックスに存在しない場合は追加されます。
レコード更新
検索可能モデルを更新するには、モデルインスタンスのプロパティを更新し、save
でモデルをデータベースへ保存します。Scoutは自動的に変更を検索インデックスへ保存します。
use App\Models\Order;
$order = Order::find(1);
// 注文を更新…
$order->save();
Eloquentクエリインスタンスでsearchable
メソッドを呼び出して、モデルのコレクションを更新することもできます。モデルが検索インデックスに存在しない場合は作成されます。
Order::where('price', '>', 100)->searchable();
リレーションシップ内のすべてのモデルの検索インデックスレコードを更新する場合は、リレーションシップインスタンスでsearchable
を呼び出すことができます。
$user->orders()->searchable();
または、メモリ内にEloquentモデルのコレクションが既にある場合は、コレクションインスタンスでsearchable
メソッドを呼び出して、対応するインデックスのモデルインスタンスを更新できます。
$orders->searchable();
レコード削除
インデックスからレコードを削除するには、データベースからモデルをdelete
するだけです。これは、ソフトデリートモデルを使用している場合でも実行できます。
use App\Models\Order;
$order = Order::find(1);
$order->delete();
レコードを削除する前にモデルを取得したくない場合は、Eloquentクエリインスタンスでunsearchable
メソッドを使用できます。
Order::where('price', '>', 100)->unsearchable();
リレーション内のすべてのモデルの検索インデックスレコードを削除する場合は、リレーションインスタンスでunsearchable
を呼び出してください。
$user->orders()->unsearchable();
または、メモリ内にEloquentモデルのコレクションが既にある場合は、コレクションインスタンスでunsearchable
メソッドを呼び出して、対応するインデックスからモデルインスタンスを削除できます。
$orders->unsearchable();
インデックスの一時停止
モデルデータを検索インデックスに同期せずに、モデルに対してEloquent操作のバッチを実行する必要がある場合があります。これは、withoutSyncingToSearch
メソッドを使用して行うことができます。このメソッドは、すぐに実行される単一のクロージャを引数に取ります。クロージャ内で発行するモデル操作は、モデルのインデックスに同期されません。
use App\Models\Order;
Order::withoutSyncingToSearch(function () {
// モデルアクションを実行
});
条件付き検索可能モデルインスタンス
特定の条件下でのみ、モデルを検索可能にする必要がある場合も起きるでしょう。たとえば、App\Models\Post
モデルが、"draft"か"published"の2つのうち、どちらか1つの状態を取ると想像してください。「公開済み:published」のポストのみ検索可能にする必要があります。これを実現するには、モデルにshouldBeSearchable
メソッドを定義してください。
/**
* モデルを検索可能にする判定
*
* @return bool
*/
public function shouldBeSearchable()
{
return $this->isPublished();
}
shouldBeSearchable
メソッドは、save
およびcreate
メソッド、クエリ、またはリレーションを通してモデルを操作する場合にのみ適用されます。searchable
メソッドを使用してモデルまたはコレクションを直接検索可能にすると、shouldBeSearchable
メソッドの結果が上書きされます。
Warning!! 検索可能なデータは常にデータベースへ保存されるため、
shouldBeSearchable
メソッドはScoutの「データベース」エンジンを使用する際には適用されません。データベースエンジン使用時に同様の動作をさせるには、代わりにWHERE句を使用する必要があります。
検索
search
メソッドにより、モデルの検索を開始しましょう。search
メソッドはモデルを検索するために使用する文字列だけを引数に指定します。get
メソッドを検索クエリにチェーンし、指定した検索クエリに一致するEloquentモデルを取得できます。
use App\Models\Order;
$orders = Order::search('Star Trek')->get();
Scoutの検索ではEloquentモデルのコレクションが返されるため、ルートやコントローラから直接結果を返せば、自動的にJSONへ変換されます。
use App\Models\Order;
use Illuminate\Http\Request;
Route::get('/search', function (Request $request) {
return Order::search($request->search)->get();
});
Eloquentモデルへ変換する前に素の検索結果を取得したい場合は、raw
メソッドを使用できます。
$orders = Order::search('Star Trek')->raw();
カスタムインデックス
検索クエリは通常、モデルのsearchableAs
メソッドで指定するインデックスに対して実行されます。ただし、within
メソッドを使用して、代わりに検索する必要があるカスタムインデックスを指定できます。
$orders = Order::search('Star Trek')
->within('tv_shows_popularity_desc')
->get();
Where節
Scoutを使用すると、検索クエリに単純な「where」節を追加できます。現在、これらの節は基本的な数値の同等性チェックのみをサポートしており、主に所有者IDによる検索クエリのスコープに役立ちます。
use App\Models\Order;
$orders = Order::search('Star Trek')->where('user_id', 1)->get();
whereIn
メソッドを使用すると、指定された値の集合に対して結果を制約できます。
$orders = Order::search('Star Trek')->whereIn(
'status', ['paid', 'open']
)->get();
検索インデックスはリレーショナルデータベースではないため、より高度な"where"節は現在サポートしていません。
Warning!! If your application is using MeiliSearch, you must configure your application's filterable attributes before utilizing Scout's "where" clauses.
ペジネーション
モデルのコレクションを取得することに加えて、paginate
メソッドを使用して検索結果をページ分割することができます。このメソッドは、従来のEloquentクエリをペジネーションする場合と同じように、Illuminate\Pagination\LengthAwarePaginator
インスタンスを返します。
use App\Models\Order;
$orders = Order::search('Star Trek')->paginate();
paginate
メソッドの第1引数として、各ページごとに取得したいモデル数を指定します。
$orders = Order::search('Star Trek')->paginate(15);
結果が取得できたら、通常のEloquentクエリのペジネーションと同様に、結果を表示し、Bladeを使用してページリンクをレンダできます。
<div class="container">
@foreach ($orders as $order)
{{ $order->price }}
@endforeach
</div>
{{ $orders->links() }}
もちろん、ペジネーションの結果をJSONとして取得したい場合は、ルートまたはコントローラから直接ペジネータインスタンスを返すことができます。
use App\Models\Order;
use Illuminate\Http\Request;
Route::get('/orders', function (Request $request) {
return Order::search($request->input('query'))->paginate(15);
});
Warning!! 検索エンジンはEloquentモデルのグローバルスコープ定義を認識しないため、Scoutのペジネーションを利用するアプリケーションではグローバルスコープを使うべきでありません。それでも、Scoutにより検索する場合は、グローバルスコープの制約を再作成する必要があります。
ソフトデリート
インデックス付きのモデルがソフトデリートされ、ソフトデリート済みのモデルをサーチする必要がある場合、config/scout.php
設定ファイルのsoft_delete
オプションをtrue
に設定してください。
'soft_delete' => true,
この設定オプションをtrue
にすると、Scoutは検索インデックスからソフトデリートされたモデルを削除しません。代わりに、インデックスされたレコードへ、隠し__soft_deleted
属性をセットします。これにより、検索時にソフトデリート済みレコードを取得するために、withTrashed
やonlyTrashed
メソッドがつかえます。
use App\Models\Order;
// 結果の取得時に、削除済みレコードも含める
$orders = Order::search('Star Trek')->withTrashed()->get();
// 結果の取得時に、削除済みレコードのみを対象とする
$orders = Order::search('Star Trek')->onlyTrashed()->get();
Note: ソフトデリートされたモデルが、
forceDelete
により完全に削除されると、Scoutは自動的に検索インデックスから削除します。
エンジンの検索のカスタマイズ
エンジンの検索動作の高度なカスタマイズを実行する必要がある場合は、
search
メソッドの2番目の引数にクロージャを渡せます。たとえば、このコールバックを使用して、検索クエリがAlgoliaに渡される前に、地理的位置データを検索オプションに追加できます。
use Algolia\AlgoliaSearch\SearchIndex;
use App\Models\Order;
Order::search(
'Star Trek',
function (SearchIndex $algolia, string $query, array $options) {
$options['body']['query']['bool']['filter']['geo_distance'] = [
'distance' => '1000km',
'location' => ['lat' => 36, 'lon' => 111],
];
return $algolia->search($query, $options);
}
)->get();
Eloquent結果のクエリのカスタマイズ
Scoutはアプリケーションの検索エンジンからマッチするEloquentモデルのリストを取得した後、Eloquentを使用して主キーでマッチするすべてのモデルを取得しようとします。このクエリはquery
メソッドを呼び出し、カスタマイズできます。query
メソッドは、Eloquentクエリビルダのインスタンスを引数とするクロージャを受け取ります。
use App\Models\Order;
$orders = Order::search('Star Trek')
->query(fn ($query) => $query->with('invoices'))
->get();
このコールバックは、関連モデルがアプリケーションの検索エンジンからあらかじめ取得された後に呼び出されるので、query
メソッドを結果の「フィルタリング」に使用しないでください。代わりに、Scout WHERE句を使用してください。
カスタムエンジン
エンジンのプログラミング
組み込みのScout検索エンジンがニーズに合わない場合、独自のカスタムエンジンを書き、Scoutへ登録してください。エンジンは、Laravel\Scout\Engines\Engine
抽象クラスを拡張してください。この抽象クラスは、カスタムエンジンが実装する必要のある、8つのメソッドを持っています。
use Laravel\Scout\Builder;
abstract public function update($models);
abstract public function delete($models);
abstract public function search(Builder $builder);
abstract public function paginate(Builder $builder, $perPage, $page);
abstract public function mapIds($results);
abstract public function map(Builder $builder, $results, $model);
abstract public function getTotalCount($results);
abstract public function flush($model);
これらのメソッドの実装をレビューするために、Laravel\Scout\Engines\AlgoliaEngine
クラスが役に立つでしょう。このクラスは独自エンジンで、各メソッドをどのように実装すればよいかの、良い取り掛かりになるでしょう。
エンジンの登録
カスタムエンジンを作成したら、Scoutエンジンマネージャのextend
メソッドを使用してScoutへ登録します。Scoutのエンジンマネージャは、Laravelサービスコンテナが依存解決できます。App\Providers\AppServiceProvider
クラスのboot
メソッドまたはアプリケーションが使用している他のサービスプロバイダからextend
メソッドを呼び出せます。
use App\ScoutExtensions\MySqlSearchEngine
use Laravel\Scout\EngineManager;
/**
* 全アプリケーションサービスの初期起動処理
*
* @return void
*/
public function boot()
{
resolve(EngineManager::class)->extend('mysql', function () {
return new MySqlSearchEngine;
});
}
エンジンを登録したら、アプリケーションのconfig/scout.php
設定ファイルでデフォルトのスカウトdriver
として指定できます。
'driver' => 'mysql',
ビルダマクロ
カスタムのScout検索ビルダメソッドを定義する場合は、Laravel\Scout\Builder
クラスでmacro
メソッドが使用できます。通常、「マクロ」はサービスプロバイダのboot
メソッド内で定義する必要があります。
use Illuminate\Support\Facades\Response;
use Illuminate\Support\ServiceProvider;
use Laravel\Scout\Builder;
/**
* 全アプリケーションサービスの初期起動処理
*
* @return void
*/
public function boot()
{
Builder::macro('count', function () {
return $this->engine->getTotalCount(
$this->engine()->search($this)
);
});
}
macro
関数は、最初の引数にマクロ名、2番目の引数にクロージャを取ります。マクロのクロージャは、Laravel\Scout\Builder
実装からマクロ名を呼び出すときに実行されます。
use App\Models\Order;
Order::search('Star Trek')->count();