跳到主要內容

Laravel Scout

📝 此頁面為 Laravel 官方文檔的繁體中文翻譯。查看原始英文版本

Laravel Scout

簡介

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

Scout 附帶了一個內建的 database 引擎,該引擎使用 MySQL/PostgreSQL 全文索引和 LIKE 子句來搜尋您現有的資料庫 — 無需外部服務。對於大多數應用程式來說,這就是您所需要的。要了解 Laravel 中所有可用的搜尋選項,請查閱搜尋文件

當您需要容錯、分面過濾或大規模地理搜尋等功能時,Scout 還包含了用於 AlgoliaMeilisearchTypesense 的驅動程式。還有一個用於本地開發的「集合」驅動程式,您也可以自由編寫自訂引擎

安裝

首先,透過 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 trait 新增到您希望使其可搜尋的模型中。此 trait 將註冊一個模型觀察器,自動使模型與您的搜尋驅動程式保持同步:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;
}

佇列

使用非 databasecollection 引擎時,強烈建議在使用該函式庫之前配置一個佇列驅動程式。執行佇列工作程式將允許 Scout 將所有同步模型資訊到搜尋索引的操作排入佇列,從而為應用程式的 Web 界面提供更好的回應時間。

一旦您配置了佇列驅動程式,將 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

唯一任務

在寫入密集型應用程式中,您可能希望防止 Scout 為相同的模型記錄排隊重複的任務。您可以透過註冊 MakeSearchableUniquelyRemoveFromSearchUniquely 任務類別來選擇唯一索引任務,通常在服務提供者的 boot 方法中進行:

use Laravel\Scout\Jobs\MakeSearchableUniquely;
use Laravel\Scout\Jobs\RemoveFromSearchUniquely;
use Laravel\Scout\Scout;

Scout::makeSearchableUsing(MakeSearchableUniquely::class);
Scout::removeFromSearchUsing(RemoveFromSearchUniquely::class);

這些任務使用 Laravel 的唯一任務鎖定來避免在已存在匹配的可搜尋模型記錄的排隊索引操作時分發重複的索引操作。

驅動程式先決條件

Algolia

使用 Algolia 驅動程式時,您應在 config/scout.php 配置檔中配置您的 Algolia idsecret 憑證。配置好憑證後,您還需要透過 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 hostkey 憑證:

SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey

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

此外,您應透過查閱 Meilisearch 關於二進位相容性的文件,確保安裝的 meilisearch/meilisearch-php 版本與您的 Meilisearch 二進位版本相容。

[!WARNING] 在使用 Meilisearch 的應用程式上升級 Scout 時,您應始終查閱 Meilisearch 服務本身的任何其他重大變更

Typesense

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

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

要開始在 Scout 中使用 Typesense,請透過 Composer 套件管理器安裝 Typesense PHP SDK:

composer require typesense/typesense-php

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

SCOUT_DRIVER=typesense
TYPESENSE_API_KEY=masterKey
TYPESENSE_HOST=localhost

如果您正在使用 Laravel Sail,可能需要調整 TYPESENSE_HOST 環境變數以匹配 Docker 容器名稱。您還可以選擇指定安裝的連接埠、路徑和協定:

TYPESENSE_PORT=8108
TYPESENSE_PATH=
TYPESENSE_PROTOCOL=http

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

配置

配置可搜尋資料

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

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;

    public function toSearchableArray(): array
    {
        return [
            'title' => $this->title,
            'content' => $this->content,
        ];
    }
}

要配置搜尋索引中儲存的內容,您還可能需要使用 unsearchablesearchableAfter 方法。有關詳細資訊,請查閱條件式可搜尋模型實例部分。此外,您還可能想要自訂模型 ID 並定義標註。

配置模型 ID

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

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class User extends Model
{
    use Searchable;

    public function getScoutKey(): mixed
    {
        return $this->email;
    }
}

配置模型索引

每個可搜尋模型都與一個搜尋索引相關聯,該索引包含所有可搜尋記錄。Scout 將根據模型的「表格」名稱(通常是模型的「使用者」名稱)自動推斷索引名稱。您可以透過覆寫模型上的 searchableAs 方法來自訂索引名稱:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;

    public function searchableAs(): string
    {
        return 'posts_index';
    }
}

資料庫/集合引擎

資料庫引擎

database 引擎使用 MySQL 和 PostgreSQL 的全文索引功能以及 LIKE 子句來搜尋您的現有資料庫。當使用 database 引擎時,所有搜尋索引操作會立即執行,因此 Searc hable 模型的任何變更都會立即在搜尋結果中反映。此引擎不需要外部服務或依賴項,並且對於大多數應用程式來說應該足夠。

要使用 database 引擎,只需在應用程式的 .env 檔案中將 SCOUT_DRIVER 環境變數的值設定為 database

SCOUT_DRIVER=database

集合引擎

collection 引擎主要用於本地開發和或不需要外部搜尋引擎的簡單搜尋操作。此引擎將在記憶體中過濾所有模型記錄的集合。它不支援除搜尋之外的其他 Scout 功能(如 simplePaginate)。使用 collection 引擎時,不需要外部依賴項。

要使用 collection 引擎,只需將應用程式 .env 檔案中的 SCOUT_DRIVER 環境變數值設定為 collection

SCOUT_DRIVER=collection

第三方引擎配置

配置模型索引

每個可搜尋模型都與一個搜尋索引相關聯,該索引包含所有可搜尋記錄。您可以透過覆寫模型上的 searchableAs 方法來自訂索引名稱:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;

    public function searchableAs(): string
    {
        return 'posts_index';
    }
}

Algolia 配置

使用 Algolia 驅動程式時,應在 config/scout.php 中配置您的 idsecret 憑證。配置好憑證後,還需要安裝 Algolia PHP SDK:

composer require algolia/algoliasearch-client-php

Meilisearch 配置

使用 Meilisearch 驅動程式時,應安裝 Meilisearch PHP SDK:

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

然後在 .env 中設定 SCOUT_DRIVER 以及 Meilisearch 的 hostkey

SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey

Typesense 配置

使用 Typesense 驅動程式時,應安裝 Typesense PHP SDK:

composer require typesense/typesense-php

然後在 .env 中設定環境變數:

SCOUT_DRIVER=typesense
TYPESENSE_API_KEY=masterKey
TYPESENSE_HOST=localhost

Typesense 集合的其他設定可以在 config/scout.php 中找到。

第三方引擎索引

批次匯入

如果您要將 Scout 安裝到現有專案上,您可能已經有了需要匯入到搜尋引擎的模型記錄。Scout 提供了一個 scout:import Artisan 命令,用於將現有記錄匯入到您的搜尋索引中:

php artisan scout:import App\Models\Post

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

php artisan scout:flush App\Models\Post

新增記錄

一旦您在模型上添加了 Laravel\Scout\Searchable trait,您只需要 save 一個模型實例,它就會自動新增到您的搜尋索引中。如果您配置了佇列,此操作將在您的佇列工作者處理時由背景排程:

use App\Models\Order;

$order = new Order(...);

$order->save();

透過查詢新增記錄

如果您想透過 Eloquent 查詢將模型集合新增到搜尋索引,您可以在 Eloquent 查詢建構器上鏈式呼叫 searchable 方法。如果您批次匯入現有記錄,這會很有用:

use App\Models\Order;

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

更新記錄

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

use App\Models\Order;

$order = Order::find(1);

$order->price = 200;

$order->save();

您也可以在 Eloquent 查詢建構器上使用 searchable 方法來更新模型集合。如果您需要重新索引模型集合,這會很有用。例如,您可以使用 searchable 方法在月度銷售報告上更新價格:

Order::where('created_at', '<', now()->subMonth())->searchable();

刪除記錄

要從資料庫中刪除記錄,只需使用 Eloquent 的 delete 方法。記錄將自動從您的搜尋索引中移除。如果您使用佇列來處理搜尋更新,它將在背景處理:

use App\Models\Order;

$order = Order::find(1);

$order->delete();

如果您想跳過從搜尋索引中刪除記錄,可以使用模型的 unsearchable 方法:

use App\Models\Order;

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

暫停索引

有時您可能需要在不影響搜尋索引的情況下對模型執行一批 Eloquent 操作。您可以使用 withoutSyncingToSearch 方法在給定的回呼中暫停索引,並防止模型資料同步到您的搜尋索引:

use App\Models\Order;

Order::withoutSyncingToSearch(function () {
    Order::factory()->count(10)->create();
});

條件式可搜尋模型實例

有時您可能只想使某些模型可搜尋。例如,假設您的 App\Models\Post 模型有「draft」和「published」兩種狀態。您可能只想允許搜尋「published」的文章。要實現此目的,您可以在模型上定義一個 shouldBeSearchable 方法:

public function shouldBeSearchable(): bool
{
    return $this->isPublished();
}

shouldBeSearchable 方法在透過 makeAllSearchable 或透過建立/儲存/save 操作建立搜尋記錄時應用。但是,在透過查詢或關聯直接新增或更新記錄時,將不考慮此方法。如下一章所述,您可以透過使用 searchableAfter 方法或 unsearchable 方法來覆寫此行為。

搜尋後方法

即使 shouldBeSearchable 返回 false,您可能仍然希望能夠使模型可搜尋。例如,將文章狀態從「draft」更改為「published」時。為此,您可以定義一個 searchableAfter 方法。當該方法返回 true 時,模型將被新增到搜尋索引中:

public function shouldBeSearchable(): bool
{
    return $this->isPublished;
}

public function searchableAfter(): bool
{
    return $this->isDirty('status') && $this->isPublished;
}

搜尋

您可以使用 search 方法開始搜尋模型。search 方法接受一個將用於搜尋您的模型的單一字串。然後,您可以將搜尋條件鏈式呼叫到查詢建構器上:

use App\Models\Order;

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

由於 Scout 搜尋返回 Eloquent 模型的集合,您可以直接從路由或控制器返回結果,Laravel 將自動將其轉換為 JSON 回應:

use App\Models\Order;

Route::get('/search', function () {
    return Order::search(request('search'))->get();
});

Where 子句

Scout 允許您向搜尋查詢新增簡單的「where」子句。目前,這些 where 子句僅支援基本數值相等檢查,主要用於按擁有者的 ID 範圍限定搜尋查詢。由於搜尋引擎不是關聯式資料庫,目前不支援更高階的「where」子句:

use App\Models\Order;

$orders = Order::search('Star Trek')->where('user_id', 1)->get();

分頁

除了檢索模型集合之外,您還可以使用 paginate 方法對搜尋結果進行分頁。此方法將返回一個類似於傳統 Eloquent 查詢分頁Illuminate\Contracts\Pagination\LengthAwarePaginator 實例:

use App\Models\Order;

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

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

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

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

檢索結果後,您可以像使用傳統 Laravel 分頁一樣顯示結果並使用 Blade 渲染分頁連結:

<div class="container">
    @foreach ($orders as $order)
        {{ $order->price }}
    @endforeach
</div>

{{ $orders->links() }}

軟刪除

如果您的可搜尋模型正在使用軟刪除,並且您需要從搜尋索引中隱藏軟刪除的模型,則應在應用程式的 AppServiceProvider 或另一個服務提供者的 boot 方法中呼叫 SoftDeletes trait:

use App\Models\Order;
use Illuminate\Database\Eloquent\SoftDeletes;

public function boot(): void
{
    Order::SoftDeletes();
}

自訂引擎搜尋

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

use Algolia\AlgoliaSearch\SearchIndex;
use App\Models\Order;

Order::search(
    'Star Trek',
    function (SearchIndex $algolia, string $query, array $options) {
        $options['aroundLatLng'] = 'lat,lng';

        return $algolia->search($query, $options);
    }
)->get();

自訂引擎

如果內建的 Scout 搜尋引擎都不滿足您的需求,您可以編寫自訂引擎並在 Scout 中註冊它。要開始,請為您的引擎定義一個類別。您的類別應實作 Laravel\Scout\Engine 契約。此契約包含八個方法:

use Laravel\Scout\Builder;
use Laravel\Scout\Engine;

class MyEngine implements Engine
{
    // ...
}

一旦您實作了自訂引擎,您可以在應用程式的服務提供者中註冊它,例如 AppServiceProviderboot 方法:

use Laravel\Scout\EngineManager;

public function boot(): void
{
    resolve(EngineManager::class)->extend('my-engine', function () {
        return new MyEngine;
    });
}

註冊引擎後,您可以將應用程式的 .env 檔案中的 SCOUT_DRIVER 環境變數更新為 my-engine