Laravel Scout
簡介
Laravel Scout 提供一個簡單、基於驅動程式的解決方案,可為您的 Eloquent 模型新增全文搜尋。透過使用模型觀察者,Scout 將自動讓您的搜尋索引與您的 Eloquent 記錄保持同步。
目前,Scout 隨附 Algolia、Meilisearch、Typesense 和 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;}
佇列
雖然並非使用 Scout 的絕對必要條件,但在使用程式庫之前,您應該強烈考慮設定佇列驅動程式。執行佇列工作者將允許 Scout 將所有同步模型資訊至搜尋索引的操作放入佇列,從而為您應用程式的網頁介面提供更佳的響應時間。
設定佇列驅動程式後,將 config/scout.php
設定檔中的 queue
選項值設定為 true
'queue' => true,
即使 queue
選項設定為 false
,也務必記住某些 Scout 驅動程式(例如 Algolia 和 Meilisearch)始終會以非同步方式索引記錄。也就是說,即使索引操作已在您的 Laravel 應用程式內完成,搜尋引擎本身可能不會立即反映新的和更新的記錄。
若要指定您的 Scout 工作利用的連線和佇列,您可以將 queue
設定選項定義為陣列
'queue' => [ 'connection' => 'redis', 'queue' => 'scout'],
當然,如果您自訂 Scout 工作利用的連線和佇列,您應該執行佇列工作者以處理該連線和佇列上的工作
php artisan queue:work redis --queue=scout
驅動程式先決條件
Algolia
使用 Algolia 驅動程式時,您應該在 config/scout.php
設定檔中設定您的 Algolia id
和 secret
憑證。設定憑證後,您還需要透過 Composer 套件管理器安裝 Algolia PHP SDK
composer require algolia/algoliasearch-client-php
Meilisearch
Meilisearch 是一個快速且開源的搜尋引擎。如果您不確定如何在您的本機電腦上安裝 Meilisearch,您可以使用 Laravel Sail,這是 Laravel 官方支援的 Docker 開發環境。
使用 Meilisearch 驅動程式時,您需要透過 Composer 套件管理器安裝 Meilisearch PHP SDK
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
然後,在您應用程式的 .env
檔案中設定 SCOUT_DRIVER
環境變數以及您的 Meilisearch host
和 key
憑證
SCOUT_DRIVER=meilisearchMEILISEARCH_HOST=http://127.0.0.1:7700MEILISEARCH_KEY=masterKey
如需有關 Meilisearch 的詳細資訊,請參閱 Meilisearch 文件。
此外,您應該透過檢閱 Meilisearch 關於二進位相容性的文件,確保您安裝的 meilisearch/meilisearch-php
版本與您的 Meilisearch 二進位版本相容。
在使用 Meilisearch 的應用程式上升級 Scout 時,您應該始終檢閱 Meilisearch 服務本身的任何其他重大變更。
Typesense
Typesense 是一個速度極快的開源搜尋引擎,支援關鍵字搜尋、語意搜尋、地理搜尋和向量搜尋。
您可以自行託管 Typesense 或使用 Typesense Cloud。
若要開始使用 Typesense 和 Scout,請透過 Composer 套件管理器安裝 Typesense PHP SDK
composer require typesense/typesense-php
然後,在您應用程式的 .env 檔案中設定 SCOUT_DRIVER
環境變數以及您的 Typesense 主機和 API 金鑰憑證
SCOUT_DRIVER=typesenseTYPESENSE_API_KEY=masterKeyTYPESENSE_HOST=localhost
如果您使用 Laravel Sail,您可能需要調整 TYPESENSE_HOST
環境變數以符合 Docker 容器名稱。您也可以選擇性地指定您安裝的埠、路徑和協定
TYPESENSE_PORT=8108TYPESENSE_PATH=TYPESENSE_PROTOCOL=http
您的 Typesense 集合的其他設定和結構定義可以在您應用程式的 config/scout.php
設定檔中找到。如需有關 Typesense 的詳細資訊,請參閱 Typesense 文件。
準備要儲存在 Typesense 中的資料
使用 Typesense 時,您的可搜尋模型必須定義一個 toSearchableArray
方法,該方法會將您模型的主鍵轉換為字串,並將建立日期轉換為 UNIX 時間戳記
/** * Get the indexable data array for the model. * * @return array<string, mixed> */public function toSearchableArray(){ return array_merge($this->toArray(),[ 'id' => (string) $this->id, 'created_at' => $this->created_at->timestamp, ]);}
您也應該在您應用程式的 config/scout.php
檔案中定義您的 Typesense 集合結構定義。集合結構定義會描述每個可透過 Typesense 搜尋的欄位的資料類型。如需所有可用結構選項的詳細資訊,請參閱 Typesense 文件。
如果您需要在定義 Typesense 集合的結構定義之後進行變更,您可以執行 scout:flush
和 scout:import
,這會刪除所有現有索引資料並重新建立結構定義。或者,您可以使用 Typesense 的 API 來修改集合的結構定義,而不會移除任何索引資料。
如果您的可搜尋模型是可軟刪除的,您應該在您應用程式的 config/scout.php
設定檔中的模型對應 Typesense 結構定義中定義 __soft_deleted
欄位
User::class => [ 'collection-schema' => [ 'fields' => [ // ... [ 'name' => '__soft_deleted', 'type' => 'int32', 'optional' => true, ], ], ],],
動態搜尋參數
Typesense 允許您在透過 options
方法執行搜尋操作時動態修改您的搜尋參數
use App\Models\Todo; Todo::search('Groceries')->options([ 'query_by' => 'title, description'])->get();
設定
設定模型索引
每個 Eloquent 模型都與一個指定的搜尋「索引」同步,其中包含該模型的所有可搜尋記錄。換句話說,您可以將每個索引視為 MySQL 資料表。根據預設,每個模型都會保存到符合模型一般「資料表」名稱的索引中。通常,這是模型名稱的複數形式;但是,您可以自由透過覆寫模型上的 searchableAs
方法來自訂模型的索引
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model;use Laravel\Scout\Searchable; class Post extends Model{ use Searchable; /** * Get the name of the index associated with the model. */ public function searchableAs(): string { return 'posts_index'; }}
設定可搜尋的資料
預設情況下,指定模型的所有 toArray
格式數據都會被儲存到其搜尋索引中。如果您想自訂同步到搜尋索引的數據,可以覆寫模型上的 toSearchableArray
方法。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model;use Laravel\Scout\Searchable; class Post extends Model{ use Searchable; /** * Get the indexable data array for the model. * * @return array<string, mixed> */ public function toSearchableArray(): array { $array = $this->toArray(); // Customize the data array... return $array; }}
某些搜尋引擎(如 Meilisearch)只會對正確類型的數據執行篩選操作(>
、<
等)。因此,當使用這些搜尋引擎並自訂您的可搜尋數據時,您應確保數值被轉換為它們正確的類型。
public function toSearchableArray(){ return [ 'id' => (int) $this->id, 'name' => $this->name, 'price' => (float) $this->price, ];}
設定可篩選數據和索引設定 (Meilisearch)
與 Scout 的其他驅動程式不同,Meilisearch 需要您預先定義索引搜尋設定,例如可篩選的屬性、可排序的屬性,以及其他支援的設定欄位。
可篩選的屬性是您在調用 Scout 的 where
方法時計劃用於篩選的任何屬性,而可排序的屬性是您在調用 Scout 的 orderBy
方法時計劃用於排序的任何屬性。要定義您的索引設定,請調整應用程式 scout
設定檔中 meilisearch
設定項的 index-settings
部分。
use App\Models\User;use App\Models\Flight; 'meilisearch' => [ 'host' => env('MEILISEARCH_HOST', 'https://127.0.0.1:7700'), 'key' => env('MEILISEARCH_KEY', null), 'index-settings' => [ User::class => [ 'filterableAttributes'=> ['id', 'name', 'email'], 'sortableAttributes' => ['created_at'], // Other settings fields... ], 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; /** * Get the value used to index the model. */ public function getScoutKey(): mixed { return $this->email; } /** * Get the key name used to index the model. */ public function getScoutKeyName(): mixed { return 'email'; }}
為每個模型設定搜尋引擎
在搜尋時,Scout 通常會使用您應用程式 scout
設定檔中指定的預設搜尋引擎。但是,特定模型的搜尋引擎可以通過覆寫模型上的 searchableUsing
方法來更改。
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model;use Laravel\Scout\Engines\Engine;use Laravel\Scout\EngineManager;use Laravel\Scout\Searchable; class User extends Model{ use Searchable; /** * Get the engine used to index the model. */ public function searchableUsing(): Engine { return app(EngineManager::class)->engine('meilisearch'); }}
識別使用者
當使用 Algolia 時,Scout 還允許您自動識別使用者。在 Algolia 的儀表板中查看您的搜尋分析時,將已驗證的使用者與搜尋操作關聯起來可能會很有幫助。您可以在應用程式的 .env
檔案中將 SCOUT_IDENTIFY
環境變數定義為 true
來啟用使用者識別。
SCOUT_IDENTIFY=true
啟用此功能也會將請求的 IP 位址和您已驗證使用者的主要識別符傳遞給 Algolia,以便此數據與使用者發出的任何搜尋請求相關聯。
資料庫 / 集合引擎
資料庫引擎
資料庫引擎目前支援 MySQL 和 PostgreSQL。
如果您的應用程式與小型到中型的資料庫互動或工作負載較輕,您可能會發現使用 Scout 的「資料庫」引擎更方便。當從您現有的資料庫篩選結果以確定適用於您查詢的搜尋結果時,資料庫引擎將使用「where like」子句和全文索引。
要使用資料庫引擎,您可以簡單地將 SCOUT_DRIVER
環境變數的值設定為 database
,或直接在應用程式的 scout
設定檔中指定 database
驅動程式。
SCOUT_DRIVER=database
一旦您將資料庫引擎指定為首選驅動程式,您必須設定您的可搜尋數據。然後,您可以開始針對您的模型執行搜尋查詢。當使用資料庫引擎時,不需要搜尋引擎索引,例如將資料匯入 Algolia、Meilisearch 或 Typesense 索引所需的索引。
自訂資料庫搜尋策略
預設情況下,資料庫引擎將針對您設定為可搜尋的每個模型屬性執行「where like」查詢。但是,在某些情況下,這可能會導致效能不佳。因此,可以設定資料庫引擎的搜尋策略,以便某些指定的列使用全文搜尋查詢,或僅使用「where like」約束來搜尋字串的前綴 (example%
),而不是在整個字串中搜尋 (%example%
)。
要定義此行為,您可以在模型的 toSearchableArray
方法中指定 PHP 屬性。任何未分配額外搜尋策略行為的列將繼續使用預設的「where like」策略。
use Laravel\Scout\Attributes\SearchUsingFullText;use Laravel\Scout\Attributes\SearchUsingPrefix; /** * Get the indexable data array for the model. * * @return array<string, mixed> */#[SearchUsingPrefix(['id', 'email'])]#[SearchUsingFullText(['bio'])]public function toSearchableArray(): array{ return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, 'bio' => $this->bio, ];}
在指定某個列應使用全文查詢約束之前,請確保該列已被分配了全文索引。
集合引擎
雖然您可以在本機開發期間自由使用 Algolia、Meilisearch 或 Typesense 搜尋引擎,但您可能會發現使用「集合」引擎更方便。「集合」引擎將使用「where」子句和對現有資料庫結果的集合篩選,以確定適用於您查詢的搜尋結果。當使用此引擎時,不需要「索引」您的可搜尋模型,因為它們將直接從您的本機資料庫中檢索。
要使用集合引擎,您可以簡單地將 SCOUT_DRIVER
環境變數的值設定為 collection
,或直接在應用程式的 scout
設定檔中指定 collection
驅動程式。
SCOUT_DRIVER=collection
一旦您將集合驅動程式指定為首選驅動程式,您就可以開始針對您的模型執行搜尋查詢。當使用集合引擎時,不需要搜尋引擎索引,例如將資料匯入 Algolia、Meilisearch 或 Typesense 索引所需的索引。
與資料庫引擎的差異
乍看之下,「資料庫」和「集合」引擎非常相似。它們都直接與您的資料庫互動以檢索搜尋結果。但是,集合引擎不使用全文索引或 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
方法。這是新增任何在匯入模型之前可能需要的預先關係載入的好地方。
use Illuminate\Database\Eloquent\Builder; /** * Modify the query used to retrieve models when making all of the models searchable. */protected function makeAllSearchableUsing(Builder $query): Builder{ return $query->with('author');}
當使用佇列批次匯入模型時,makeAllSearchableUsing
方法可能不適用。當模型集合由任務處理時,關係不會被恢復。
新增記錄
一旦您將 Laravel\Scout\Searchable
特性新增到模型中,您只需 save
或 create
一個模型實例,它就會自動新增到您的搜尋索引中。如果您已將 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();
searchable
方法可以被視為「upsert」操作。換句話說,如果模型記錄已在您的索引中,它將被更新。如果它不存在於搜尋索引中,它將被新增到索引中。
更新記錄
要更新可搜尋模型,您只需更新模型實例的屬性並將模型 save
到您的資料庫。Scout 會自動將變更儲存到您的搜尋索引中。
use App\Models\Order; $order = Order::find(1); // Update the order... $order->save();
您也可以在 Eloquent 查詢實例上調用 searchable
方法來更新模型集合。如果模型不存在於您的搜尋索引中,它們將被建立。
Order::where('price', '>', 100)->searchable();
如果您想更新關係中所有模型的搜尋索引記錄,您可以在關係實例上調用 searchable
。
$user->orders()->searchable();
或者,如果您已經在記憶體中有 Eloquent 模型集合,您可以呼叫集合實例上的 searchable
方法,以更新其對應索引中的模型實例。
$orders->searchable();
在匯入之前修改記錄
有時您可能需要在使模型可搜尋之前準備模型集合。例如,您可能想要預先載入關係,以便可以有效地將關係數據新增到您的搜尋索引中。為此,請在對應的模型上定義 makeSearchableUsing
方法。
use Illuminate\Database\Eloquent\Collection; /** * Modify the collection of models being made searchable. */public function makeSearchableUsing(Collection $models): Collection{ return $models->load('author');}
移除記錄
要從索引中刪除記錄,您可以簡單地從資料庫中 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();
要從其對應的索引中刪除模型的所有記錄,您可以調用 removeAllFromSearch
方法。
Order::removeAllFromSearch();
暫停索引
有時您可能需要在不將模型數據同步到搜尋索引的情況下,對模型執行一批 Eloquent 操作。您可以使用 withoutSyncingToSearch
方法來執行此操作。此方法接受單個閉包,該閉包將立即執行。在閉包中發生的任何模型操作都不會同步到模型的索引。
use App\Models\Order; Order::withoutSyncingToSearch(function () { // Perform model actions...});
有條件地可搜尋的模型實例
有時您可能需要在特定條件下才使模型可搜尋。例如,假設您有一個 App\Models\Post
模型,該模型可能處於兩種狀態之一:「草稿」和「已發布」。您可能只希望允許「已發布」的文章可搜尋。為此,您可以在模型上定義 shouldBeSearchable
方法。
/** * Determine if the model should be searchable. */public function shouldBeSearchable(): bool{ return $this->isPublished();}
僅當通過 save
和 create
方法、查詢或關係操作模型時,才會應用 shouldBeSearchable
方法。直接使用 searchable
方法使模型或集合可搜尋將覆蓋 shouldBeSearchable
方法的結果。
當使用 Scout 的「資料庫」引擎時,shouldBeSearchable
方法不適用,因為所有可搜尋的數據始終儲存在資料庫中。要在使用資料庫引擎時實現類似的行為,您應該改用 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', ['open', 'paid'])->get();
whereNotIn
方法會驗證給定欄位的值是否未包含在給定的陣列中
$orders = Order::search('Star Trek')->whereNotIn( 'status', ['closed'])->get();
由於搜尋索引不是關聯式資料庫,因此目前不支援更進階的 "where" 子句。
如果您的應用程式使用 Meilisearch,您必須先設定應用程式的可篩選屬性,才能使用 Scout 的 "where" 子句。
分頁
除了擷取模型集合之外,您還可以透過使用 paginate
方法來分頁您的搜尋結果。此方法將會返回一個 Illuminate\Pagination\LengthAwarePaginator
實例,就像您對傳統 Eloquent 查詢進行分頁一樣
use App\Models\Order; $orders = Order::search('Star Trek')->paginate();
您可以透過將數量作為 paginate
方法的第一個引數傳遞,來指定每頁要擷取的模型數量
$orders = Order::search('Star Trek')->paginate(15);
一旦您擷取了結果,您可以使用 Blade 顯示結果並呈現頁面連結,就像您對傳統 Eloquent 查詢進行分頁一樣
<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);});
由於搜尋引擎不知道您的 Eloquent 模型的全域範圍定義,因此您不應在利用 Scout 分頁的應用程式中使用全域範圍。或者,您應該在使用 Scout 搜尋時重新建立全域範圍的約束。
軟刪除
如果您的索引模型是軟刪除的,並且您需要搜尋軟刪除的模型,請將 config/scout.php
組態檔中的 soft_delete
選項設定為 true
'soft_delete' => true,
當此組態選項為 true
時,Scout 不會從搜尋索引中移除軟刪除的模型。相反地,它會在索引的記錄上設定一個隱藏的 __soft_deleted
屬性。然後,您可以使用 withTrashed
或 onlyTrashed
方法在搜尋時擷取軟刪除的記錄
use App\Models\Order; // Include trashed records when retrieving results...$orders = Order::search('Star Trek')->withTrashed()->get(); // Only include trashed records when retrieving results...$orders = Order::search('Star Trek')->onlyTrashed()->get();
當使用 forceDelete
永久刪除軟刪除的模型時,Scout 會自動從搜尋索引中移除它。
自訂引擎搜尋
如果您需要對引擎的搜尋行為執行進階自訂,您可以將閉包作為 search
方法的第二個引數傳遞。例如,您可以使用此回呼在將搜尋查詢傳遞給 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;use Illuminate\Database\Eloquent\Builder; $orders = Order::search('Star Trek') ->query(fn (Builder $query) => $query->with('invoices')) ->get();
由於此回呼是在從應用程式的搜尋引擎擷取相關模型之後調用的,因此不應將 query
方法用於「篩選」結果。相反地,您應該使用Scout where 子句。
自訂引擎
編寫引擎
如果其中一個內建的 Scout 搜尋引擎不符合您的需求,您可以編寫自己的自訂引擎,並將其註冊到 Scout。您的引擎應擴展 Laravel\Scout\Engines\Engine
抽象類別。此抽象類別包含您的自訂引擎必須實作的八個方法
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; /** * Bootstrap any application services. */public function boot(): void{ resolve(EngineManager::class)->extend('mysql', function () { return new MySqlSearchEngine; });}
一旦您的引擎註冊完成,您可以在應用程式的 config/scout.php
組態檔中將其指定為預設的 Scout driver
'driver' => 'mysql',