> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel Scout

> 为 Eloquent 模型添加全文检索能力的官方扩展包。支持 Meilisearch、Algolia、Typesense、database 引擎，并通过模型观察者自动同步索引。

## 简介

**Laravel Scout** 是一个基于驱动的简洁方案，用于给 [Eloquent 模型](/zh/eloquent)添加全文检索能力。它通过模型观察者，自动同步 Eloquent 记录与搜索索引。

Scout 内置了 `database` 引擎，使用 MySQL / PostgreSQL 的全文索引和 `LIKE` 子句直接搜索数据库，无需外部服务。大规模生产环境中若需要拼写容错、分面搜索、地理搜索，则可以选择外部引擎。

### 支持的引擎一览

| 引擎           | 特点                         | 适用场景    |
| ------------ | -------------------------- | ------- |
| `database`   | 使用 MySQL / PostgreSQL 全文索引 | 大多数应用   |
| `collection` | 在 PHP 内过滤（含 SQLite 也可）     | 本地开发、测试 |
| Meilisearch  | 开源，支持拼写容错，速度快              | 生产环境    |
| Algolia      | 云端 SaaS，功能丰富               | 生产环境    |
| Typesense    | 开源，支持向量检索                  | 生产环境    |

```mermaid theme={null}
flowchart LR
  APP["Laravel 应用<br>(Eloquent 模型)"] -->|"save / delete"| SCOUT["Laravel Scout<br>(模型观察者)"]
  SCOUT -->|"同步索引"| ENGINE["搜索引擎<br>Meilisearch / Algolia / Typesense"]
  USER["用户"] -->|"Model::search()"| APP
  ENGINE -->|"搜索结果"| APP
```

## 安装

通过 Composer 安装。

```shell theme={null}
composer require laravel/scout
```

安装后，使用 `vendor:publish` 命令发布配置文件，会生成 `config/scout.php`。

```shell theme={null}
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
```

最后在需要可搜索的模型上添加 `Laravel\Scout\Searchable` trait。该 trait 会注册模型观察者，实现与搜索驱动的自动同步。

```php theme={null}
<?php

namespace App\Models;

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

class Post extends Model
{
    use Searchable;
}
```

### 配置队列

使用 `database` 或 `collection` 之外的引擎时，强烈建议先配置好[队列驱动](/zh/queues)。启动队列 worker 后，索引同步会在后台执行，Web 界面的响应速度将大幅提升。

将 `config/scout.php` 中的 `queue` 设为 `true`。

```php theme={null}
'queue' => true,
```

也可以指定连接和队列名。

```php theme={null}
'queue' => [
    'connection' => 'redis',
    'queue' => 'scout'
],
```

配置好后启动专用的队列 worker。

```shell theme={null}
php artisan queue:work redis --queue=scout
```

### 使用唯一任务

在写入密集的应用中，你可能希望避免同一模型记录的重复索引任务进入队列。在 `config/scout.php` 中注册 `MakeSearchableUniquely` 和 `RemoveFromSearchUniquely` 任务类，就能使用唯一化的索引任务。通常在服务提供者的 `boot` 方法中设置。

```php theme={null}
use Laravel\Scout\Jobs\MakeSearchableUniquely;
use Laravel\Scout\Jobs\RemoveFromSearchUniquely;
use Laravel\Scout\Scout;

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

这些任务使用 Laravel 的[唯一任务锁](/zh/queues#unique-jobs)，防止已在队列中的同一模型记录被重复派发。

## 各驱动的准备工作

### Algolia

使用 Algolia 驱动时，请在 `config/scout.php` 中配置 `id` 与 `secret`，并安装 Algolia PHP SDK。

```shell theme={null}
composer require algolia/algoliasearch-client-php
```

在 `.env` 中配置凭证。

```ini theme={null}
ALGOLIA_APP_ID=your-app-id
ALGOLIA_SECRET=your-secret-key
```

#### 索引配置

Algolia 可以通过 `config/scout.php` 管理索引设置。

```php theme={null}
use App\Models\User;

'algolia' => [
    'id' => env('ALGOLIA_APP_ID', ''),
    'secret' => env('ALGOLIA_SECRET', ''),
    'index-settings' => [
        User::class => [
            'searchableAttributes' => ['id', 'name', 'email'],
            'attributesForFaceting' => ['filterOnly(email)'],
        ],
    ],
],
```

配置完毕后执行 `scout:sync-index-settings` 命令，让 Algolia 生效。

```shell theme={null}
php artisan scout:sync-index-settings
```

### Meilisearch

[Meilisearch](https://www.meilisearch.com) 是一款高性能的开源搜索引擎。本地开发中最简单的方法是使用 [Laravel Sail](https://laravel.com/docs/sail#meilisearch) 中的 Docker 服务。

```shell theme={null}
# 使用 Laravel Sail
./vendor/bin/sail up -d meilisearch
```

不使用 Sail 时，可以直接用 Docker 启动。

```shell theme={null}
docker run -it --rm \
    -p 7700:7700 \
    getmeili/meilisearch:latest \
    meilisearch --master-key="masterKey"
```

安装 Meilisearch PHP SDK。

```shell theme={null}
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
```

在 `.env` 中配置驱动与主机。

```ini theme={null}
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey
```

<Warning>
  升级 Scout 时请务必查阅 Meilisearch 本身的[破坏性变更](https://github.com/meilisearch/Meilisearch/releases)。
</Warning>

#### 索引配置（Meilisearch）

在 Meilisearch 中，用于 `where()` 过滤的字段必须提前注册到 `filterableAttributes`，用于 `orderBy()` 排序的字段则注册到 `sortableAttributes`。

```php theme={null}
use App\Models\User;

'meilisearch' => [
    'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
    'key' => env('MEILISEARCH_KEY', null),
    'index-settings' => [
        User::class => [
            'filterableAttributes' => ['id', 'name', 'email'],
            'sortableAttributes' => ['created_at'],
        ],
    ],
],
```

注意数值列的数据类型。Meilisearch 只会对类型正确的字段执行 `>`、`<` 之类的过滤操作。

```php theme={null}
public function toSearchableArray(): array
{
    return [
        'id' => (int) $this->id,
        'name' => $this->name,
        'price' => (float) $this->price,
    ];
}
```

设置完毕后执行 `scout:sync-index-settings`。

```shell theme={null}
php artisan scout:sync-index-settings
```

### Typesense

[Typesense](https://typesense.org) 是一款高性能的开源搜索引擎，支持关键字、语义、地理及向量检索。

```shell theme={null}
composer require typesense/typesense-php
```

在 `.env` 中配置连接信息。

```ini theme={null}
SCOUT_DRIVER=typesense
TYPESENSE_API_KEY=masterKey
TYPESENSE_HOST=localhost
TYPESENSE_PORT=8108
TYPESENSE_PATH=
TYPESENSE_PROTOCOL=http
```

使用 Typesense 时，`toSearchableArray` 需要把模型主键 cast 为字符串，把创建时间 cast 为 UNIX 时间戳。

```php theme={null}
public function toSearchableArray(): array
{
    return array_merge($this->toArray(), [
        'id' => (string) $this->id,
        'created_at' => $this->created_at->timestamp,
    ]);
}
```

### database / collection 引擎

如果希望在不引入外部服务的情况下添加搜索功能，这两种就是最合适的选项。

**database 引擎** 使用 MySQL / PostgreSQL 的全文索引和 `LIKE` 子句。多数应用足够使用。

```ini theme={null}
SCOUT_DRIVER=database
```

**collection 引擎** 在 PHP 中过滤，因此可在 Laravel 支持的所有数据库（包括 SQLite）上运行。适合本地开发、测试或小数据集。

```ini theme={null}
SCOUT_DRIVER=collection
```

<Info>
  数据库引擎不像外部引擎那样需要手动管理索引，它直接搜索数据库表。
</Info>

## Searchable trait

### 自定义 toSearchableArray()

默认情况下，模型的 `toArray()` 全部数据都会写入搜索索引。要自定义同步到索引的数据，可以重写 `toSearchableArray` 方法。

```php theme={null}
<?php

namespace App\Models;

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

class Post extends Model
{
    use Searchable;

    /**
     * 获取要索引的数据数组。
     *
     * @return array<string, mixed>
     */
    public function toSearchableArray(): array
    {
        $array = $this->toArray();

        // 自定义数据...

        return $array;
    }
}
```

### 自定义索引名

默认情况下模型的表名（复数）会被用作索引名。可以通过重写 `searchableAs` 来自定义。

```php theme={null}
public function searchableAs(): string
{
    return 'posts_index';
}
```

### database 引擎的搜索策略

在 database 引擎中，可以通过 PHP Attribute 为每列指定高效的搜索策略。

```php theme={null}
use Laravel\Scout\Attributes\SearchUsingFullText;
use Laravel\Scout\Attributes\SearchUsingPrefix;

#[SearchUsingPrefix(['id', 'email'])]
#[SearchUsingFullText(['bio'])]
public function toSearchableArray(): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'bio' => $this->bio,
    ];
}
```

<Warning>
  使用 `SearchUsingFullText` 之前，请确认目标字段已建立[全文索引](/zh/migrations)。
</Warning>

### 有条件地允许搜索

若只想在特定条件下让模型可被搜索，可以定义 `shouldBeSearchable` 方法。

```php theme={null}
/**
 * 判断该模型是否应可被搜索。
 */
public function shouldBeSearchable(): bool
{
    return $this->isPublished();
}
```

<Warning>
  `shouldBeSearchable` 对 database 引擎无效。要在 database 引擎上实现类似效果，请使用[where 子句](#过滤与排序)。
</Warning>

## 索引管理

<Info>
  本节命令主要针对 Algolia、Meilisearch、Typesense 等外部引擎。database 引擎无需管理索引。
</Info>

### 导入已有记录

在已有项目中引入 Scout 时，可以使用 `scout:import` 命令把已有记录导入索引。

```shell theme={null}
php artisan scout:import "App\Models\Post"
```

也可以通过队列在后台导入。

```shell theme={null}
php artisan scout:queue-import "App\Models\Post" --chunk=500
```

### 清空索引

要从索引中删除某模型的全部记录，可以使用 `scout:flush`。

```shell theme={null}
php artisan scout:flush "App\Models\Post"
```

### 暂停索引同步

想在一段 Eloquent 操作期间临时停止与索引的同步，使用 `withoutSyncingToSearch`。

```php theme={null}
use App\Models\Order;

Order::withoutSyncingToSearch(function () {
    // 内部的模型操作都不会同步到搜索索引
});
```

### 手动添加 / 删除记录

可以基于查询把一批模型加入索引。

```php theme={null}
// 加入查询结果
Order::where('price', '>', 100)->searchable();

// 通过关联加入
$user->orders()->searchable();
```

从索引中移除记录使用 `unsearchable`。

```php theme={null}
Order::where('price', '>', 100)->unsearchable();
```

模型 `delete` 时会自动从索引中删除。

## 搜索

`search` 方法用来搜索模型。再链上 `get` 就可以得到 Eloquent 模型集合。

```php theme={null}
use App\Models\Order;

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

在控制器或路由中直接返回时会自动转 JSON。

```php theme={null}
use Illuminate\Http\Request;

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

如需拿到原始搜索结果，使用 `raw` 方法。

```php theme={null}
$orders = Order::search('Star Trek')->raw();
```

### 分页

`paginate` 方法用来对搜索结果做分页，用法与普通 Eloquent 查询一致。

```php theme={null}
$orders = Order::search('Star Trek')->paginate();

// 指定每页条数
$orders = Order::search('Star Trek')->paginate(15);
```

在 database 引擎下也可以使用 `simplePaginate`，因为它不计算总数，对大数据集更高效。

```php theme={null}
$orders = Order::search('Star Trek')->simplePaginate(15);
```

Blade 模板中的展示示例：

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

{{ $orders->links() }}
```

## 过滤与排序

`where` 方法可以给搜索查询添加过滤条件。

```php theme={null}
use App\Models\Order;

// 相等过滤
$orders = Order::search('Star Trek')->where('user_id', 1)->get();

// 在数组内任一匹配
$orders = Order::search('Star Trek')->whereIn('status', ['open', 'paid'])->get();

// 不在数组内
$orders = Order::search('Star Trek')->whereNotIn('status', ['closed'])->get();
```

<Warning>
  使用 Meilisearch 时，在使用 `where` 前必须配置[可过滤字段](#索引配置meilisearch)。
</Warning>

`query` 方法用来自定义 Eloquent 查询。

```php theme={null}
use Illuminate\Database\Eloquent\Builder;

$orders = Order::search('Star Trek')
    ->query(fn (Builder $query) => $query->with('invoices'))
    ->get();
```

## Eager Loading

Scout 会先从搜索引擎获得 ID 列表，再用 Eloquent 取回模型。要避免 N+1 问题，可以在 `query` 方法内使用 `with()` 提前加载。

```php theme={null}
use App\Models\Order;
use Illuminate\Database\Eloquent\Builder;

$orders = Order::search('Star Trek')
    ->query(fn (Builder $query) => $query->with(['invoices', 'user']))
    ->get();
```

批量导入时若也需要 Eager Load 关联，可以定义 `makeAllSearchableUsing`。

```php theme={null}
use Illuminate\Database\Eloquent\Builder;

protected function makeAllSearchableUsing(Builder $query): Builder
{
    return $query->with('author');
}
```

<Warning>
  `makeAllSearchableUsing` 在通过队列进行批量导入时可能不生效。队列任务处理模型集合时不会恢复关联。
</Warning>

## 软删除

如果被索引的模型使用了[软删除](/zh/eloquent)，并希望在搜索时也能搜到已删除的模型，请把 `config/scout.php` 的 `soft_delete` 设为 `true`。

```php theme={null}
'soft_delete' => true,
```

启用后可以通过 `withTrashed` 或 `onlyTrashed` 搜索已删除记录。

```php theme={null}
// 包含已删除
$orders = Order::search('Star Trek')->withTrashed()->get();

// 仅搜索已删除
$orders = Order::search('Star Trek')->onlyTrashed()->get();
```

## 自定义引擎

若内置引擎不能满足需求，可以自行实现自定义引擎。自定义引擎需继承 `Laravel\Scout\Engines\Engine` 抽象类，并实现下面 8 个方法。

```php theme={null}
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` 类。

创建的自定义引擎需要在 `App\Providers\AppServiceProvider` 的 `boot` 方法中注册。

```php theme={null}
use App\ScoutExtensions\MySqlSearchEngine;
use Laravel\Scout\EngineManager;

public function boot(): void
{
    resolve(EngineManager::class)->extend('mysql', function () {
        return new MySqlSearchEngine;
    });
}
```

注册后在 `config/scout.php` 中作为驱动使用。

```php theme={null}
'driver' => 'mysql',
```

## 相关页面

<Card title="Eloquent ORM" icon="database" href="/zh/eloquent">
  了解 Eloquent 模型的基础用法。
</Card>

<Card title="Eloquent 关联" icon="link" href="/zh/eloquent-relationships">
  了解关联定义与 Eager Loading。
</Card>

<Card title="队列" icon="clock" href="/zh/queues">
  Scout 可以配合队列在后台异步同步索引。
</Card>


## Related topics

- [搜索](/zh/search.md)
- [MongoDB](/zh/mongodb.md)
- [Laravel Sail](/zh/sail.md)
- [2026 年 3 月 Laravel 更新](/zh/blog/changelog/202603.md)
- [Laravel Telescope](/zh/telescope.md)
