跳到內容

Laravel Scout

簡介

Laravel Scout 提供了一個簡單、基於驅動程式的解決方案,用於為您的 Eloquent 模型新增全文搜尋功能。透過使用模型觀察器,Scout 將自動使您的搜尋索引與您的 Eloquent 記錄保持同步。

目前,Scout 附帶 AlgoliaMeilisearchTypesense 和 MySQL / PostgreSQL (database) 驅動程式。此外,Scout 還包含一個「集合」驅動程式,該驅動程式專為本地開發使用而設計,並且不需要任何外部依賴或第三方服務。此外,編寫自訂驅動程式非常簡單,您可以自由使用自己的搜尋實作來擴展 Scout。

安裝

首先,透過 Composer 套件管理器安裝 Scout

1composer require laravel/scout

安裝 Scout 後,您應該使用 vendor:publish Artisan 命令發佈 Scout 設定檔。此命令會將 scout.php 設定檔發佈到您應用程式的 config 目錄中

1php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

最後,將 Laravel\Scout\Searchable trait 新增到您想要使其可搜尋的模型中。此 trait 將註冊一個模型觀察器,該觀察器將自動使模型與您的搜尋驅動程式保持同步

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Database\Eloquent\Model;
6use Laravel\Scout\Searchable;
7 
8class Post extends Model
9{
10 use Searchable;
11}

佇列

雖然並非使用 Scout 的嚴格要求,但在使用該函式庫之前,您應強烈考慮設定 佇列驅動程式。執行佇列工作程序將允許 Scout 將所有同步您的模型資訊到搜尋索引的操作排入佇列,從而為您應用程式的 Web 介面提供更好的回應時間。

設定佇列驅動程式後,將 config/scout.php 設定檔中 queue 選項的值設定為 true

1'queue' => true,

即使 queue 選項設定為 false,重要的是要記住,某些 Scout 驅動程式(如 Algolia 和 Meilisearch)始終異步索引記錄。這表示,即使索引操作已在您的 Laravel 應用程式中完成,搜尋引擎本身也可能不會立即反映新的和更新的記錄。

若要指定 Scout 任務使用的連線和佇列,您可以將 queue 設定選項定義為陣列

1'queue' => [
2 'connection' => 'redis',
3 'queue' => 'scout'
4],

當然,如果您自訂 Scout 任務使用的連線和佇列,則應執行佇列工作程序以處理該連線和佇列上的任務

1php artisan queue:work redis --queue=scout

驅動程式先決條件

Algolia

使用 Algolia 驅動程式時,您應該在 config/scout.php 設定檔中設定您的 Algolia idsecret 憑證。設定憑證後,您還需要透過 Composer 套件管理器安裝 Algolia PHP SDK

1composer require algolia/algoliasearch-client-php

Meilisearch

Meilisearch 是一個極其快速且開源的搜尋引擎。如果您不確定如何在本地電腦上安裝 Meilisearch,可以使用 Laravel Sail,這是 Laravel 官方支援的 Docker 開發環境。

使用 Meilisearch 驅動程式時,您需要透過 Composer 套件管理器安裝 Meilisearch PHP SDK

1composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle

然後,在您應用程式的 .env 檔案中設定 SCOUT_DRIVER 環境變數以及您的 Meilisearch hostkey 憑證

1SCOUT_DRIVER=meilisearch
2MEILISEARCH_HOST=http://127.0.0.1:7700
3MEILISEARCH_KEY=masterKey

有關 Meilisearch 的更多資訊,請參閱 Meilisearch 文件

此外,您應確保安裝與您的 Meilisearch 二進位版本相容的 meilisearch/meilisearch-php 版本,方法是查看 Meilisearch 關於二進位相容性的文件

在升級使用 Meilisearch 的應用程式上的 Scout 時,您應始終 查看 Meilisearch 服務本身是否有任何其他重大變更

Typesense

Typesense 是一個速度極快的開源搜尋引擎,支援關鍵字搜尋、語意搜尋、地理位置搜尋和向量搜尋。

您可以 自行託管 Typesense 或使用 Typesense Cloud

若要開始將 Typesense 與 Scout 搭配使用,請透過 Composer 套件管理器安裝 Typesense PHP SDK

1composer require typesense/typesense-php

然後,在您應用程式的 .env 檔案中設定 SCOUT_DRIVER 環境變數以及您的 Typesense 主機和 API 金鑰憑證

1SCOUT_DRIVER=typesense
2TYPESENSE_API_KEY=masterKey
3TYPESENSE_HOST=localhost

如果您使用 Laravel Sail,您可能需要調整 TYPESENSE_HOST 環境變數以符合 Docker 容器名稱。您也可以選擇性地指定安裝的埠、路徑和協定

1TYPESENSE_PORT=8108
2TYPESENSE_PATH=
3TYPESENSE_PROTOCOL=http

有關 Typesense 集合的其他設定和架構定義,可以在您應用程式的 config/scout.php 設定檔中找到。有關 Typesense 的更多資訊,請參閱 Typesense 文件

準備要在 Typesense 中儲存的資料

使用 Typesense 時,您的可搜尋模型必須定義一個 toSearchableArray 方法,該方法將您的模型主鍵轉換為字串,並將建立日期轉換為 UNIX 時間戳

1/**
2 * Get the indexable data array for the model.
3 *
4 * @return array<string, mixed>
5 */
6public function toSearchableArray()
7{
8 return array_merge($this->toArray(),[
9 'id' => (string) $this->id,
10 'created_at' => $this->created_at->timestamp,
11 ]);
12}

您還應該在應用程式的 config/scout.php 檔案中定義您的 Typesense 集合架構。集合架構描述了每個可透過 Typesense 搜尋的欄位的資料類型。有關所有可用架構選項的更多資訊,請參閱 Typesense 文件

如果您需要在定義 Typesense 集合的架構後變更它,您可以執行 scout:flushscout:import,這將刪除所有現有的索引資料並重新建立架構。或者,您可以使用 Typesense 的 API 修改集合的架構,而無需移除任何索引資料。

如果您的可搜尋模型是可軟刪除的,您應該在模型對應的 Typesense 架構中定義 __soft_deleted 欄位,該架構位於您應用程式的 config/scout.php 設定檔中

1User::class => [
2 'collection-schema' => [
3 'fields' => [
4 // ...
5 [
6 'name' => '__soft_deleted',
7 'type' => 'int32',
8 'optional' => true,
9 ],
10 ],
11 ],
12],

動態搜尋參數

Typesense 允許您在透過 options 方法執行搜尋操作時,動態修改您的 搜尋參數

1use App\Models\Todo;
2 
3Todo::search('Groceries')->options([
4 'query_by' => 'title, description'
5])->get();

設定

設定模型索引

每個 Eloquent 模型都與給定的搜尋「索引」同步,其中包含該模型的所有可搜尋記錄。換句話說,您可以將每個索引視為類似 MySQL 資料表。預設情況下,每個模型都將持久儲存到與模型典型的「資料表」名稱相符的索引中。通常,這是模型名稱的複數形式;但是,您可以透過覆寫模型上的 searchableAs 方法來自訂模型的索引

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Database\Eloquent\Model;
6use Laravel\Scout\Searchable;
7 
8class Post extends Model
9{
10 use Searchable;
11 
12 /**
13 * Get the name of the index associated with the model.
14 */
15 public function searchableAs(): string
16 {
17 return 'posts_index';
18 }
19}

設定可搜尋資料

預設情況下,給定模型的整個 toArray 形式都將持久儲存到其搜尋索引中。如果您想要自訂同步到搜尋索引的資料,您可以覆寫模型上的 toSearchableArray 方法

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Database\Eloquent\Model;
6use Laravel\Scout\Searchable;
7 
8class Post extends Model
9{
10 use Searchable;
11 
12 /**
13 * Get the indexable data array for the model.
14 *
15 * @return array<string, mixed>
16 */
17 public function toSearchableArray(): array
18 {
19 $array = $this->toArray();
20 
21 // Customize the data array...
22 
23 return $array;
24 }
25}

某些搜尋引擎(例如 Meilisearch)只會對正確類型的資料執行篩選操作 (>< 等)。因此,當使用這些搜尋引擎並自訂可搜尋資料時,您應確保數值已轉換為其正確的類型

1public function toSearchableArray()
2{
3 return [
4 'id' => (int) $this->id,
5 'name' => $this->name,
6 'price' => (float) $this->price,
7 ];
8}

設定索引設定 (Algolia)

有時您可能想要在 Algolia 索引上設定其他設定。雖然您可以透過 Algolia UI 管理這些設定,但直接從應用程式的 config/scout.php 設定檔管理索引設定的所需狀態有時更有效率。

這種方法允許您透過應用程式的自動化部署管道部署這些設定,避免手動設定並確保多個環境之間的一致性。您可以設定可篩選屬性、排名、分面或 任何其他支援的設定

若要開始使用,請在應用程式的 config/scout.php 設定檔中為每個索引新增設定

1use App\Models\User;
2use App\Models\Flight;
3 
4'algolia' => [
5 'id' => env('ALGOLIA_APP_ID', ''),
6 'secret' => env('ALGOLIA_SECRET', ''),
7 'index-settings' => [
8 User::class => [
9 'searchableAttributes' => ['id', 'name', 'email'],
10 'attributesForFaceting'=> ['filterOnly(email)'],
11 // Other settings fields...
12 ],
13 Flight::class => [
14 'searchableAttributes'=> ['id', 'destination'],
15 ],
16 ],
17],

如果給定索引的底層模型是可軟刪除的,並且包含在 index-settings 陣列中,Scout 將自動包含對該索引上軟刪除模型進行分面支援。如果您的可軟刪除模型索引沒有其他分面屬性要定義,您可以簡單地為該模型的 index-settings 陣列新增一個空項目

1'index-settings' => [
2 Flight::class => []
3],

設定應用程式的索引設定後,您必須調用 scout:sync-index-settings Artisan 命令。此命令將通知 Algolia 您目前設定的索引設定。為了方便起見,您可能希望將此命令作為部署過程的一部分

1php artisan scout:sync-index-settings

設定可篩選資料和索引設定 (Meilisearch)

與 Scout 的其他驅動程式不同,Meilisearch 要求您預先定義索引搜尋設定,例如可篩選屬性、可排序屬性和 其他支援的設定欄位

可篩選屬性是指您計劃在使用 Scout 的 where 方法時進行篩選的任何屬性,而可排序屬性是指您計劃在使用 Scout 的 orderBy 方法時進行排序的任何屬性。若要定義您的索引設定,請調整應用程式 scout 設定檔中 meilisearch 設定項目的 index-settings 部分

1use App\Models\User;
2use App\Models\Flight;
3 
4'meilisearch' => [
5 'host' => env('MEILISEARCH_HOST', 'https://127.0.0.1:7700'),
6 'key' => env('MEILISEARCH_KEY', null),
7 'index-settings' => [
8 User::class => [
9 'filterableAttributes'=> ['id', 'name', 'email'],
10 'sortableAttributes' => ['created_at'],
11 // Other settings fields...
12 ],
13 Flight::class => [
14 'filterableAttributes'=> ['id', 'destination'],
15 'sortableAttributes' => ['updated_at'],
16 ],
17 ],
18],

如果給定索引的底層模型是可軟刪除的,並且包含在 index-settings 陣列中,Scout 將自動包含對該索引上軟刪除模型進行篩選的支援。如果您的可軟刪除模型索引沒有其他可定義的篩選或排序屬性,您可以簡單地為該模型在 index-settings 陣列中新增一個空項目

1'index-settings' => [
2 Flight::class => []
3],

設定應用程式的索引設定後,您必須調用 scout:sync-index-settings Artisan 命令。此命令將通知 Meilisearch 您目前設定的索引設定。為了方便起見,您可能希望將此命令納入您的部署流程中

1php artisan scout:sync-index-settings

設定模型 ID

預設情況下,Scout 將使用模型的主鍵作為模型的唯一 ID / 鍵,該鍵儲存在搜尋索引中。如果您需要自訂此行為,您可以覆寫模型上的 getScoutKeygetScoutKeyName 方法

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Database\Eloquent\Model;
6use Laravel\Scout\Searchable;
7 
8class User extends Model
9{
10 use Searchable;
11 
12 /**
13 * Get the value used to index the model.
14 */
15 public function getScoutKey(): mixed
16 {
17 return $this->email;
18 }
19 
20 /**
21 * Get the key name used to index the model.
22 */
23 public function getScoutKeyName(): mixed
24 {
25 return 'email';
26 }
27}

為每個模型設定搜尋引擎

搜尋時,Scout 通常會使用在應用程式的 scout 設定檔中指定的預設搜尋引擎。但是,可以通過覆寫模型上的 searchableUsing 方法來更改特定模型的搜尋引擎

1<?php
2 
3namespace App\Models;
4 
5use Illuminate\Database\Eloquent\Model;
6use Laravel\Scout\Engines\Engine;
7use Laravel\Scout\EngineManager;
8use Laravel\Scout\Searchable;
9 
10class User extends Model
11{
12 use Searchable;
13 
14 /**
15 * Get the engine used to index the model.
16 */
17 public function searchableUsing(): Engine
18 {
19 return app(EngineManager::class)->engine('meilisearch');
20 }
21}

識別使用者

Scout 還允許您在使用 Algolia 時自動識別使用者。將已驗證的使用者與搜尋操作關聯,在 Algolia 儀表板中查看您的搜尋分析時可能會有所幫助。您可以通過在應用程式的 .env 檔案中將 SCOUT_IDENTIFY 環境變數定義為 true 來啟用使用者識別

1SCOUT_IDENTIFY=true

啟用此功能也將把請求的 IP 位址和已驗證使用者的主要識別符傳遞給 Algolia,以便此資料與使用者發出的任何搜尋請求相關聯。

資料庫 / 集合引擎

資料庫引擎

資料庫引擎目前支援 MySQL 和 PostgreSQL。

如果您的應用程式與中小型資料庫互動或工作負載較輕,您可能會發現使用 Scout 的「資料庫」引擎更方便入門。資料庫引擎將在從現有資料庫篩選結果時使用「where like」子句和全文索引,以確定適用於您的查詢的搜尋結果。

若要使用資料庫引擎,您可以簡單地將 SCOUT_DRIVER 環境變數的值設定為 database,或直接在應用程式的 scout 設定檔中指定 database 驅動程式

1SCOUT_DRIVER=database

一旦您將資料庫引擎指定為首選驅動程式,您必須設定您的可搜尋資料。然後,您可以開始對您的模型執行搜尋查詢。當使用資料庫引擎時,不需要搜尋引擎索引,例如為 Algolia、Meilisearch 或 Typesense 索引建立種子所需的索引。

自訂資料庫搜尋策略

預設情況下,資料庫引擎將針對您已設定為可搜尋的每個模型屬性執行「where like」查詢。但是,在某些情況下,這可能會導致效能不佳。因此,可以設定資料庫引擎的搜尋策略,以便某些指定的資料行使用全文搜尋查詢,或僅使用「where like」約束來搜尋字串的前綴 (example%),而不是搜尋整個字串 (%example%)。

若要定義此行為,您可以將 PHP 屬性指派給模型的 toSearchableArray 方法。任何未指派額外搜尋策略行為的資料行將繼續使用預設的「where like」策略

1use Laravel\Scout\Attributes\SearchUsingFullText;
2use Laravel\Scout\Attributes\SearchUsingPrefix;
3 
4/**
5 * Get the indexable data array for the model.
6 *
7 * @return array<string, mixed>
8 */
9#[SearchUsingPrefix(['id', 'email'])]
10#[SearchUsingFullText(['bio'])]
11public function toSearchableArray(): array
12{
13 return [
14 'id' => $this->id,
15 'name' => $this->name,
16 'email' => $this->email,
17 'bio' => $this->bio,
18 ];
19}

在指定資料行應使用全文查詢約束之前,請確保已為該資料行指派全文索引

集合引擎

雖然您可以自由地在本地開發期間使用 Algolia、Meilisearch 或 Typesense 搜尋引擎,但您可能會發現使用「集合」引擎更方便入門。集合引擎將使用「where」子句和集合篩選來篩選現有資料庫的結果,以確定適用於您的查詢的搜尋結果。當使用此引擎時,不需要「索引」您的可搜尋模型,因為它們將僅從您的本地資料庫中檢索。

若要使用集合引擎,您可以簡單地將 SCOUT_DRIVER 環境變數的值設定為 collection,或直接在應用程式的 scout 設定檔中指定 collection 驅動程式

1SCOUT_DRIVER=collection

一旦您將集合驅動程式指定為首選驅動程式,您可以開始對您的模型執行搜尋查詢。當使用集合引擎時,不需要搜尋引擎索引,例如為 Algolia、Meilisearch 或 Typesense 索引建立種子所需的索引。

與資料庫引擎的不同之處

乍看之下,「資料庫」和「集合」引擎非常相似。它們都直接與您的資料庫互動以檢索搜尋結果。但是,集合引擎不使用全文索引或 LIKE 子句來尋找匹配的記錄。相反,它會拉取所有可能的記錄,並使用 Laravel 的 Str::is 輔助函數來確定搜尋字串是否存在於模型屬性值中。

集合引擎是最具可移植性的搜尋引擎,因為它適用於 Laravel 支援的所有關聯式資料庫(包括 SQLite 和 SQL Server);但是,它的效率不如 Scout 的資料庫引擎。

索引

批次匯入

如果您要將 Scout 安裝到現有專案中,您可能已經有需要匯入到索引中的資料庫記錄。Scout 提供了 scout:import Artisan 命令,您可以使用它將所有現有記錄匯入到您的搜尋索引中

1php artisan scout:import "App\Models\Post"

flush 命令可用於從您的搜尋索引中移除模型的所有記錄

1php artisan scout:flush "App\Models\Post"

修改匯入查詢

如果您想修改用於檢索所有模型以進行批次匯入的查詢,您可以在模型上定義 makeAllSearchableUsing 方法。這是新增任何在匯入模型之前可能需要的預先載入關係的好地方

1use Illuminate\Database\Eloquent\Builder;
2 
3/**
4 * Modify the query used to retrieve models when making all of the models searchable.
5 */
6protected function makeAllSearchableUsing(Builder $query): Builder
7{
8 return $query->with('author');
9}

當使用佇列來批次匯入模型時,makeAllSearchableUsing 方法可能不適用。當模型集合由任務處理時,關係不會還原

新增記錄

一旦您將 Laravel\Scout\Searchable 特性新增到模型中,您只需 savecreate 模型實例,它就會自動新增到您的搜尋索引中。如果您已將 Scout 設定為使用佇列,則此操作將由您的佇列工作程序在背景中執行

1use App\Models\Order;
2 
3$order = new Order;
4 
5// ...
6 
7$order->save();

通過查詢新增記錄

如果您想通過 Eloquent 查詢將模型集合新增到您的搜尋索引,您可以將 searchable 方法鏈接到 Eloquent 查詢上。searchable 方法將分塊處理查詢結果,並將記錄新增到您的搜尋索引中。同樣,如果您已將 Scout 設定為使用佇列,則所有區塊都將由您的佇列工作程序在背景中匯入

1use App\Models\Order;
2 
3Order::where('price', '>', 100)->searchable();

您也可以在 Eloquent 關係實例上調用 searchable 方法

1$user->orders()->searchable();

或者,如果您已經在記憶體中擁有 Eloquent 模型集合,您可以在集合實例上調用 searchable 方法,將模型實例新增到其對應的索引中

1$orders->searchable();

searchable 方法可以被視為「upsert」操作。換句話說,如果模型記錄已存在於您的索引中,它將被更新。如果它不存在於搜尋索引中,它將被新增到索引中。

更新記錄

若要更新可搜尋模型,您只需更新模型實例的屬性並 save 模型到您的資料庫。Scout 將自動將變更持久化到您的搜尋索引

1use App\Models\Order;
2 
3$order = Order::find(1);
4 
5// Update the order...
6 
7$order->save();

您也可以在 Eloquent 查詢實例上調用 searchable 方法來更新模型集合。如果模型不存在於您的搜尋索引中,它們將被建立

1Order::where('price', '>', 100)->searchable();

如果您想更新關係中所有模型的搜尋索引記錄,您可以在關係實例上調用 searchable

1$user->orders()->searchable();

或者,如果您已經在記憶體中擁有 Eloquent 模型集合,您可以在集合實例上調用 searchable 方法,以更新模型實例在其對應索引中的記錄

1$orders->searchable();

匯入前修改記錄

有時您可能需要在模型集合可搜尋之前準備它們。例如,您可能想要預先載入關係,以便可以有效地將關係資料新增到您的搜尋索引中。若要完成此操作,請在對應的模型上定義 makeSearchableUsing 方法

1use Illuminate\Database\Eloquent\Collection;
2 
3/**
4 * Modify the collection of models being made searchable.
5 */
6public function makeSearchableUsing(Collection $models): Collection
7{
8 return $models->load('author');
9}

移除記錄

若要從索引中移除記錄,您可以簡單地從資料庫中 delete 模型。即使您使用軟刪除模型,也可以這樣做

1use App\Models\Order;
2 
3$order = Order::find(1);
4 
5$order->delete();

如果您不想在刪除記錄之前檢索模型,您可以在 Eloquent 查詢實例上使用 unsearchable 方法

1Order::where('price', '>', 100)->unsearchable();

如果您想移除關係中所有模型的搜尋索引記錄,您可以在關係實例上調用 unsearchable

1$user->orders()->unsearchable();

或者,如果您已經在記憶體中擁有 Eloquent 模型集合,您可以在集合實例上調用 unsearchable 方法,從其對應的索引中移除模型實例

1$orders->unsearchable();

若要從其對應的索引中移除所有模型記錄,您可以調用 removeAllFromSearch 方法

1Order::removeAllFromSearch();

暫停索引

有時您可能需要在模型上執行一批 Eloquent 操作,而無需將模型資料同步到您的搜尋索引。您可以使用 withoutSyncingToSearch 方法執行此操作。此方法接受一個閉包,該閉包將立即執行。在閉包內發生的任何模型操作都不會同步到模型的索引

1use App\Models\Order;
2 
3Order::withoutSyncingToSearch(function () {
4 // Perform model actions...
5});

有條件地可搜尋的模型實例

有時您可能需要僅在特定條件下使模型可搜尋。例如,假設您有一個 App\Models\Post 模型,它可能處於兩種狀態之一:「草稿」和「已發布」。您可能只想允許「已發布」的文章可搜尋。若要完成此操作,您可以在模型上定義 shouldBeSearchable 方法

1/**
2 * Determine if the model should be searchable.
3 */
4public function shouldBeSearchable(): bool
5{
6 return $this->isPublished();
7}

shouldBeSearchable 方法僅在通過 savecreate 方法、查詢或關係操作模型時應用。直接使用 searchable 方法使模型或集合可搜尋將覆寫 shouldBeSearchable 方法的結果。

當使用 Scout 的「資料庫」引擎時,shouldBeSearchable 方法不適用,因為所有可搜尋資料始終儲存在資料庫中。若要在使用資料庫引擎時實現類似的行為,您應該改用where 子句

搜尋

您可以使用 search 方法開始搜尋模型。search 方法接受一個字串,該字串將用於搜尋您的模型。然後,您應該將 get 方法鏈接到搜尋查詢上,以檢索與給定搜尋查詢匹配的 Eloquent 模型

1use App\Models\Order;
2 
3$orders = Order::search('Star Trek')->get();

由於 Scout 搜尋返回 Eloquent 模型集合,您甚至可以直接從路由或控制器返回結果,它們將自動轉換為 JSON

1use App\Models\Order;
2use Illuminate\Http\Request;
3 
4Route::get('/search', function (Request $request) {
5 return Order::search($request->search)->get();
6});

如果您想在搜尋結果轉換為 Eloquent 模型之前取得原始搜尋結果,您可以使用 raw 方法

1$orders = Order::search('Star Trek')->raw();

自訂索引

搜尋查詢通常會在模型的searchableAs 方法指定的索引上執行。但是,您可以使用 within 方法來指定應搜尋的自訂索引

1$orders = Order::search('Star Trek')
2 ->within('tv_shows_popularity_desc')
3 ->get();

Where 條件子句

Scout 允許您向搜尋查詢新增簡單的「where」子句。目前,這些子句僅支援基本的數值相等性檢查,主要用於按所有者 ID 劃分搜尋查詢的範圍

1use App\Models\Order;
2 
3$orders = Order::search('Star Trek')->where('user_id', 1)->get();

此外,whereIn 方法可用於驗證給定資料行的值是否包含在給定陣列中

1$orders = Order::search('Star Trek')->whereIn(
2 'status', ['open', 'paid']
3)->get();

whereNotIn 方法驗證給定資料行的值是否未包含在給定陣列中

1$orders = Order::search('Star Trek')->whereNotIn(
2 'status', ['closed']
3)->get();

由於搜尋索引不是關聯式資料庫,因此目前不支援更進階的「where」子句。

如果您的應用程式正在使用 Meilisearch,您必須在利用 Scout 的「where」子句之前,設定應用程式的可篩選屬性

分頁

除了檢索模型集合外,您可以使用 paginate 方法對搜尋結果進行分頁。此方法將返回 Illuminate\Pagination\LengthAwarePaginator 實例,就像您已分頁傳統 Eloquent 查詢一樣

1use App\Models\Order;
2 
3$orders = Order::search('Star Trek')->paginate();

您可以通過將數量作為第一個參數傳遞給 paginate 方法來指定每頁檢索多少模型

1$orders = Order::search('Star Trek')->paginate(15);

檢索結果後,您可以像分頁傳統 Eloquent 查詢一樣,使用 Blade 顯示結果並呈現頁面連結

1<div class="container">
2 @foreach ($orders as $order)
3 {{ $order->price }}
4 @endforeach
5</div>
6 
7{{ $orders->links() }}

當然,如果您想以 JSON 格式檢索分頁結果,您可以直接從路由或控制器返回分頁器實例

1use App\Models\Order;
2use Illuminate\Http\Request;
3 
4Route::get('/orders', function (Request $request) {
5 return Order::search($request->input('query'))->paginate(15);
6});

由於搜尋引擎不知道您的 Eloquent 模型的全域範圍定義,因此您不應在使用 Scout 分頁的應用程式中使用全域範圍。或者,您應該在使用 Scout 搜尋時重新建立全域範圍的約束。

軟刪除

如果您的索引模型是軟刪除,並且您需要搜尋您的軟刪除模型,請將 config/scout.php 設定檔的 soft_delete 選項設定為 true

1'soft_delete' => true,

當此設定選項為 true 時,Scout 將不會從搜尋索引中移除軟刪除模型。相反,它將在索引記錄上設定一個隱藏的 __soft_deleted 屬性。然後,您可以使用 withTrashedonlyTrashed 方法在搜尋時檢索軟刪除記錄

1use App\Models\Order;
2 
3// Include trashed records when retrieving results...
4$orders = Order::search('Star Trek')->withTrashed()->get();
5 
6// Only include trashed records when retrieving results...
7$orders = Order::search('Star Trek')->onlyTrashed()->get();

當使用 forceDelete 永久刪除軟刪除模型時,Scout 將自動從搜尋索引中移除它。

自訂引擎搜尋

如果您需要對引擎的搜尋行為執行進階自訂,您可以將閉包作為第二個參數傳遞給 search 方法。例如,您可以使用此回呼在搜尋查詢傳遞給 Algolia 之前,將地理位置資料新增到您的搜尋選項

1use Algolia\AlgoliaSearch\SearchIndex;
2use App\Models\Order;
3 
4Order::search(
5 'Star Trek',
6 function (SearchIndex $algolia, string $query, array $options) {
7 $options['body']['query']['bool']['filter']['geo_distance'] = [
8 'distance' => '1000km',
9 'location' => ['lat' => 36, 'lon' => 111],
10 ];
11 
12 return $algolia->search($query, $options);
13 }
14)->get();

自訂 Eloquent 結果查詢

在 Scout 從您的應用程式的搜尋引擎中檢索到符合條件的 Eloquent 模型列表後,Eloquent 會被用來透過模型的主鍵檢索所有符合條件的模型。您可以透過調用 query 方法來自訂此查詢。query 方法接受一個閉包(closure),該閉包將接收 Eloquent query builder 實例作為參數。

1use App\Models\Order;
2use Illuminate\Database\Eloquent\Builder;
3 
4$orders = Order::search('Star Trek')
5 ->query(fn (Builder $query) => $query->with('invoices'))
6 ->get();

由於此回呼函數是在相關模型已從您的應用程式的搜尋引擎中檢索之後才調用,因此 query 方法不應該被用於「過濾」結果。相反地,您應該使用Scout where 條件子句

自訂引擎

撰寫引擎

如果內建的 Scout 搜尋引擎不符合您的需求,您可以撰寫自己的自訂引擎並將其註冊到 Scout。您的引擎應該繼承 Laravel\Scout\Engines\Engine 抽象類別。此抽象類別包含您的自訂引擎必須實作的八個方法。

1use Laravel\Scout\Builder;
2 
3abstract public function update($models);
4abstract public function delete($models);
5abstract public function search(Builder $builder);
6abstract public function paginate(Builder $builder, $perPage, $page);
7abstract public function mapIds($results);
8abstract public function map(Builder $builder, $results, $model);
9abstract public function getTotalCount($results);
10abstract public function flush($model);

您可能會發現檢閱 Laravel\Scout\Engines\AlgoliaEngine 類別上這些方法的實作方式很有幫助。這個類別將為您提供一個良好的起點,以學習如何在您自己的引擎中實作這些方法中的每一個。

註冊引擎

一旦您撰寫了自訂引擎,您可以使用 Scout 引擎管理器的 extend 方法將其註冊到 Scout。Scout 的引擎管理器可以從 Laravel 服務容器中解析。您應該從 App\Providers\AppServiceProvider 類別或您的應用程式使用的任何其他服務提供者的 boot 方法中呼叫 extend 方法。

1use App\ScoutExtensions\MySqlSearchEngine;
2use Laravel\Scout\EngineManager;
3 
4/**
5 * Bootstrap any application services.
6 */
7public function boot(): void
8{
9 resolve(EngineManager::class)->extend('mysql', function () {
10 return new MySqlSearchEngine;
11 });
12}

一旦您的引擎被註冊,您可以在您的應用程式的 config/scout.php 設定檔中將其指定為您的預設 Scout driver

1'driver' => 'mysql',

Laravel 是最具生產力的方式來
建構、部署和監控軟體。