翻译进度
19
分块数量
3
参与人数

Scout

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。


Laravel Scout

简介

Laravel Scout 提供了一种基于驱动的简单解决方案,用于给你的 Eloquent 模型 添加全文搜索功能。Scout 使用模型观察器,会自动保持你的搜索索引与 Eloquent 记录同步。

目前,Scout 自带了 AlgoliaMeilisearchTypesense,以及 MySQL / PostgreSQL (database) 驱动。除此之外,Scout 还包含一个专为本地开发使用设计的 “collection” 驱动,它不需要任何外部依赖或第三方服务。并且,编写自定义驱动也很简单,你可以自由扩展 Scout 来实现自己的搜索功能。

安装

首先,通过 Composer 包管理器安装 Scout:

composer require laravel/scout

安装完成后,你应该使用 vendor:publish Artisan 命令发布 Scout 的配置文件。该命令会将 scout.php 配置文件发布到应用的 config 目录中:

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
无与伦比 翻译于 4天前

最后,把 Laravel\Scout\Searchable trait 添加到你想要设置为可搜索的模型中。这个 trait 会注册一个模型观察器,它会自动保持模型与搜索驱动同步:

<?php

namespace App\Models;

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

class Post extends Model
{
    use Searchable;
}

队列

虽然使用 Scout 并不严格要求,但在使用该库之前,你应该强烈考虑配置一个 队列驱动。运行队列工作器将允许 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
无与伦比 翻译于 4天前

驱动先决条件

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-php 版本与所使用的 Meilisearch 二进制版本兼容,可以参考 Meilisearch 关于二进制兼容性的文档

[!警告]
当在一个使用 Meilisearch 的应用中升级 Scout 时,你应当始终 检查 Meilisearch 服务本身的额外重大变更

Typesense

Typesense 是一个极速、开源的搜索引擎,支持关键词搜索、语义搜索、地理搜索以及向量搜索。

无与伦比 翻译于 4天前

你可以选择 自托管 Typesense,或者使用 Typesense Cloud

要在 Scout 中开始使用 Typesense,请通过 Composer 包管理器安装 Typesense PHP SDK:

composer require typesense/typesense-php

然后,在应用的 .env 文件中设置 SCOUT_DRIVER 环境变量,以及 Typesense 的主机和 API key 凭证:

SCOUT_DRIVER=typesense
TYPESENSE_API_KEY=masterKey
TYPESENSE_HOST=localhost

如果你正在使用 Laravel Sail,你可能需要调整 TYPESENSE_HOST 环境变量以匹配 Docker 容器的名称。你也可以选择性地指定安装的端口、路径和协议:

TYPESENSE_PORT=8108
TYPESENSE_PATH=
TYPESENSE_PROTOCOL=http

关于 Typesense 集合的额外设置和 schema 定义,可以在应用的 config/scout.php 配置文件中找到。更多关于 Typesense 的信息,请参考 Typesense 文档

为存储到 Typesense 做数据准备

在使用 Typesense 时,你的可搜索模型必须定义一个 toSearchableArray 方法,将模型的主键转换为字符串,并将创建日期转换为 UNIX 时间戳:

/**
 * 获取该模型的可索引数据数组
 *
 * @return array<string, mixed>
 */
public function toSearchableArray(): array
{
    return array_merge($this->toArray(),[
        'id' => (string) $this->id,
        'created_at' => $this->created_at->timestamp,
    ]);
}

你还应该在应用的 config/scout.php 文件中定义 Typesense 集合的 schema。集合 schema 描述了每个可通过 Typesense 搜索的字段的数据类型。有关所有可用 schema 选项的更多信息,请参考 Typesense 文档

无与伦比 翻译于 4天前

如果你需要在定义 Typesense 集合架构之后进行修改,你可以选择以下两种方式之一:
执行 scout:flushscout: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;

    /**
     * 获取与模型关联的索引名称.
     */
    public function searchableAs(): string
    {
        return 'posts_index';
    }
}
weilikai 翻译于 2天前

配置可搜索数据

默认情况下,模型的整个 toArray 结果会被保存到搜索索引中。
如果你想自定义哪些数据需要同步到搜索索引,可以在模型中重写 toSearchableArray 方法:

<?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;
    }
}

一些搜索引擎(例如 Meilisearch)在执行过滤操作时(比如 >、< 等比较),只会对数据类型正确的字段有效。
所以,当你在使用这些搜索引擎并自定义可搜索数据时,必须确保数值字段被转换成真正的数字类型,而不是字符串,否则过滤和比较可能无法正常工作:

public function toSearchableArray()
{
    return [
        'id' => (int) $this->id,
        'name' => $this->name,
        'price' => (float) $this->price,
    ];
}

配置索引设置 (Algolia)

有时候,你可能希望为 Algolia 索引 配置一些额外的设置。你可以通过 Algolia 的 UI 来管理这些设置,也可以直接在应用的 config/scout.php 配置文件中管理索引配置状态会更高效。这种方式的优点,可以通过应用的自动化部署流程发布这些设置,避免手动配置,保证多个环境中的设置保持一致。
在配置中设置 可过滤属性(filterable attributes)、排序规则(ranking)、分面(faceting),或者其他 Algolia 支持的设置。
要开始使用,只需在应用的 config/scout.php 文件中,为每个索引添加对应的设置即可:

use App\Models\User;
use App\Models\Flight;

'algolia' => [
    'id' => env('ALGOLIA_APP_ID', ''),
    'secret' => env('ALGOLIA_SECRET', ''),
    'index-settings' => [
        User::class => [
            'searchableAttributes' => ['id', 'name', 'email'],
            'attributesForFaceting'=> ['filterOnly(email)'],
            // 其他设置字段...
        ],
        Flight::class => [
            'searchableAttributes'=> ['id', 'destination'],
        ],
    ],
],
weilikai 翻译于 2天前

If the model underlying a given index is soft deletable and is included in the index-settings array, Scout will automatically include support for faceting on soft deleted models on that index. If you have no other faceting attributes to define for a soft deletable model index, you may simply add an empty entry to the index-settings array for that model:

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

After configuring your application's index settings, you must invoke the scout:sync-index-settings Artisan command. This command will inform Algolia of your currently configured index settings. For convenience, you may wish to make this command part of your deployment process:

php artisan scout:sync-index-settings

Configuring Filterable Data and Index Settings (Meilisearch)

Unlike Scout's other drivers, Meilisearch requires you to pre-define index search settings such as filterable attributes, sortable attributes, and other supported settings fields.

Filterable attributes are any attributes you plan to filter on when invoking Scout's where method, while sortable attributes are any attributes you plan to sort by when invoking Scout's orderBy method. To define your index settings, adjust the index-settings portion of your meilisearch configuration entry in your application's scout configuration file:

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'],
            // Other settings fields...
        ],
        Flight::class => [
            'filterableAttributes'=> ['id', 'destination'],
            'sortableAttributes' => ['updated_at'],
        ],
    ],
],

If the model underlying a given index is soft deletable and is included in the index-settings array, Scout will automatically include support for filtering on soft deleted models on that index. If you have no other filterable or sortable attributes to define for a soft deletable model index, you may simply add an empty entry to the index-settings array for that model:

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

After configuring your application's index settings, you must invoke the scout:sync-index-settings Artisan command. This command will inform Meilisearch of your currently configured index settings. For convenience, you may wish to make this command part of your deployment process:

php artisan scout:sync-index-settings

Configuring the Model ID

By default, Scout will use the primary key of the model as the model's unique ID / key that is stored in the search index. If you need to customize this behavior, you may override the getScoutKey and the getScoutKeyName methods on the model:

<?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';
    }
}

Configuring Search Engines per Model

When searching, Scout will typically use the default search engine specified in your application's scout configuration file. However, the search engine for a particular model can be changed by overriding the searchableUsing method on the model:

<?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');
    }
}

Identifying Users

Scout also allows you to auto identify users when using Algolia. Associating the authenticated user with search operations may be helpful when viewing your search analytics within Algolia's dashboard. You can enable user identification by defining a SCOUT_IDENTIFY environment variable as true in your application's .env file:

SCOUT_IDENTIFY=true

Enabling this feature will also pass the request's IP address and your authenticated user's primary identifier to Algolia so this data is associated with any search request that is made by the user.

Database / Collection Engines

Database Engine

[!WARNING]
The database engine currently supports MySQL and PostgreSQL.

If your application interacts with small to medium sized databases or has a light workload, you may find it more convenient to get started with Scout's "database" engine. The database engine will use "where like" clauses and full text indexes when filtering results from your existing database to determine the applicable search results for your query.

To use the database engine, you may simply set the value of the SCOUT_DRIVER environment variable to database, or specify the database driver directly in your application's scout configuration file:

SCOUT_DRIVER=database

Once you have specified the database engine as your preferred driver, you must configure your searchable data. Then, you may start executing search queries against your models. Search engine indexing, such as the indexing needed to seed Algolia, Meilisearch or Typesense indexes, is unnecessary when using the database engine.

Customizing Database Searching Strategies

By default, the database engine will execute a "where like" query against every model attribute that you have configured as searchable. However, in some situations, this may result in poor performance. Therefore, the database engine's search strategy can be configured so that some specified columns utilize full text search queries or only use "where like" constraints to search the prefixes of strings (example%) instead of searching within the entire string (%example%).

To define this behavior, you may assign PHP attributes to your model's toSearchableArray method. Any columns that are not assigned additional search strategy behavior will continue to use the default "where like" strategy:

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,
    ];
}

[!WARNING]
Before specifying that a column should use full text query constraints, ensure that the column has been assigned a full text index.

Collection Engine

While you are free to use the Algolia, Meilisearch, or Typesense search engines during local development, you may find it more convenient to get started with the "collection" engine. The collection engine will use "where" clauses and collection filtering on results from your existing database to determine the applicable search results for your query. When using this engine, it is not necessary to "index" your searchable models, as they will simply be retrieved from your local database.

To use the collection engine, you may simply set the value of the SCOUT_DRIVER environment variable to collection, or specify the collection driver directly in your application's scout configuration file:

SCOUT_DRIVER=collection

Once you have specified the collection driver as your preferred driver, you may start executing search queries against your models. Search engine indexing, such as the indexing needed to seed Algolia, Meilisearch, or Typesense indexes, is unnecessary when using the collection engine.

Differences From Database Engine

On first glance, the "database" and "collections" engines are fairly similar. They both interact directly with your database to retrieve search results. However, the collection engine does not utilize full text indexes or LIKE clauses to find matching records. Instead, it pulls all possible records and uses Laravel's Str::is helper to determine if the search string exists within the model attribute values.

The collection engine is the most portable search engine as it works across all relational databases supported by Laravel (including SQLite and SQL Server); however, it is less efficient than Scout's database engine.

Indexing

Batch Import

If you are installing Scout into an existing project, you may already have database records you need to import into your indexes. Scout provides a scout:import Artisan command that you may use to import all of your existing records into your search indexes:

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

The flush command may be used to remove all of a model's records from your search indexes:

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

Modifying the Import Query

If you would like to modify the query that is used to retrieve all of your models for batch importing, you may define a makeAllSearchableUsing method on your model. This is a great place to add any eager relationship loading that may be necessary before importing your models:

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');
}

[!WARNING]
The makeAllSearchableUsing method may not be applicable when using a queue to batch import models. Relationships are not restored when model collections are processed by jobs.

Adding Records

Once you have added the Laravel\Scout\Searchable trait to a model, all you need to do is save or create a model instance and it will automatically be added to your search index. If you have configured Scout to use queues this operation will be performed in the background by your queue worker:

use App\Models\Order;

$order = new Order;

// ...

$order->save();

Adding Records via Query

If you would like to add a collection of models to your search index via an Eloquent query, you may chain the searchable method onto the Eloquent query. The searchable method will chunk the results of the query and add the records to your search index. Again, if you have configured Scout to use queues, all of the chunks will be imported in the background by your queue workers:

use App\Models\Order;

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

You may also call the searchable method on an Eloquent relationship instance:

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

Or, if you already have a collection of Eloquent models in memory, you may call the searchable method on the collection instance to add the model instances to their corresponding index:

$orders->searchable();

[!NOTE]
The searchable method can be considered an "upsert" operation. In other words, if the model record is already in your index, it will be updated. If it does not exist in the search index, it will be added to the index.

Updating Records

To update a searchable model, you only need to update the model instance's properties and save the model to your database. Scout will automatically persist the changes to your search index:

use App\Models\Order;

$order = Order::find(1);

// Update the order...

$order->save();

You may also invoke the searchable method on an Eloquent query instance to update a collection of models. If the models do not exist in your search index, they will be created:

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

If you would like to update the search index records for all of the models in a relationship, you may invoke the searchable on the relationship instance:

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

Or, if you already have a collection of Eloquent models in memory, you may call the searchable method on the collection instance to update the model instances in their corresponding index:

$orders->searchable();

Modifying Records Before Importing

Sometimes you may need to prepare the collection of models before they are made searchable. For instance, you may want to eager load a relationship so that the relationship data can be efficiently added to your search index. To accomplish this, define a makeSearchableUsing method on the corresponding model:

use Illuminate\Database\Eloquent\Collection;

/**
 * Modify the collection of models being made searchable.
 */
public function makeSearchableUsing(Collection $models): Collection
{
    return $models->load('author');
}

Removing Records

To remove a record from your index you may simply delete the model from the database. This may be done even if you are using soft deleted models:

use App\Models\Order;

$order = Order::find(1);

$order->delete();

If you do not want to retrieve the model before deleting the record, you may use the unsearchable method on an Eloquent query instance:

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

If you would like to remove the search index records for all of the models in a relationship, you may invoke the unsearchable on the relationship instance:

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

Or, if you already have a collection of Eloquent models in memory, you may call the unsearchable method on the collection instance to remove the model instances from their corresponding index:

$orders->unsearchable();

To remove all of the model records from their corresponding index, you may invoke the removeAllFromSearch method:

Order::removeAllFromSearch();

Pausing Indexing

Sometimes you may need to perform a batch of Eloquent operations on a model without syncing the model data to your search index. You may do this using the withoutSyncingToSearch method. This method accepts a single closure which will be immediately executed. Any model operations that occur within the closure will not be synced to the model's index:

use App\Models\Order;

Order::withoutSyncingToSearch(function () {
    // Perform model actions...
});

Conditionally Searchable Model Instances

Sometimes you may need to only make a model searchable under certain conditions. For example, imagine you have App\Models\Post model that may be in one of two states: "draft" and "published". You may only want to allow "published" posts to be searchable. To accomplish this, you may define a shouldBeSearchable method on your model:

/**
 * Determine if the model should be searchable.
 */
public function shouldBeSearchable(): bool
{
    return $this->isPublished();
}

The shouldBeSearchable method is only applied when manipulating models through the save and create methods, queries, or relationships. Directly making models or collections searchable using the searchable method will override the result of the shouldBeSearchable method.

[!WARNING]
The shouldBeSearchable method is not applicable when using Scout's "database" engine, as all searchable data is always stored in the database. To achieve similar behavior when using the database engine, you should use where clauses instead.

Searching

You may begin searching a model using the search method. The search method accepts a single string that will be used to search your models. You should then chain the get method onto the search query to retrieve the Eloquent models that match the given search query:

use App\Models\Order;

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

Since Scout searches return a collection of Eloquent models, you may even return the results directly from a route or controller and they will automatically be converted to JSON:

use App\Models\Order;
use Illuminate\Http\Request;

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

If you would like to get the raw search results before they are converted to Eloquent models, you may use the raw method:

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

Custom Indexes

Search queries will typically be performed on the index specified by the model's searchableAs method. However, you may use the within method to specify a custom index that should be searched instead:

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

Where Clauses

Scout allows you to add simple "where" clauses to your search queries. Currently, these clauses only support basic numeric equality checks and are primarily useful for scoping search queries by an owner ID:

use App\Models\Order;

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

In addition, the whereIn method may be used to verify that a given column's value is contained within the given array:

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

The whereNotIn method verifies that the given column's value is not contained in the given array:

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

Since a search index is not a relational database, more advanced "where" clauses are not currently supported.

[!WARNING]
If your application is using Meilisearch, you must configure your application's filterable attributes before utilizing Scout's "where" clauses.

Pagination

In addition to retrieving a collection of models, you may paginate your search results using the paginate method. This method will return an Illuminate\Pagination\LengthAwarePaginator instance just as if you had paginated a traditional Eloquent query:

use App\Models\Order;

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

You may specify how many models to retrieve per page by passing the amount as the first argument to the paginate method:

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

Once you have retrieved the results, you may display the results and render the page links using Blade just as if you had paginated a traditional Eloquent query:

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

{{ $orders->links() }}

Of course, if you would like to retrieve the pagination results as JSON, you may return the paginator instance directly from a route or controller:

use App\Models\Order;
use Illuminate\Http\Request;

Route::get('/orders', function (Request $request) {
    return Order::search($request->input('query'))->paginate(15);
});

[!WARNING]
Since search engines are not aware of your Eloquent model's global scope definitions, you should not utilize global scopes in applications that utilize Scout pagination. Or, you should recreate the global scope's constraints when searching via Scout.

Soft Deleting

If your indexed models are soft deleting and you need to search your soft deleted models, set the soft_delete option of the config/scout.php configuration file to true:

'soft_delete' => true,

When this configuration option is true, Scout will not remove soft deleted models from the search index. Instead, it will set a hidden __soft_deleted attribute on the indexed record. Then, you may use the withTrashed or onlyTrashed methods to retrieve the soft deleted records when searching:

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();

[!NOTE]
When a soft deleted model is permanently deleted using forceDelete, Scout will remove it from the search index automatically.

Customizing Engine Searches

If you need to perform advanced customization of the search behavior of an engine you may pass a closure as the second argument to the search method. For example, you could use this callback to add geo-location data to your search options before the search query is passed to 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();

Customizing the Eloquent Results Query

After Scout retrieves a list of matching Eloquent models from your application's search engine, Eloquent is used to retrieve all of the matching models by their primary keys. You may customize this query by invoking the query method. The query method accepts a closure that will receive the Eloquent query builder instance as an argument:

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

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

Since this callback is invoked after the relevant models have already been retrieved from your application's search engine, the query method should not be used for "filtering" results. Instead, you should use Scout where clauses.

Custom Engines

Writing the Engine

If one of the built-in Scout search engines doesn't fit your needs, you may write your own custom engine and register it with Scout. Your engine should extend the Laravel\Scout\Engines\Engine abstract class. This abstract class contains eight methods your custom engine must implement:

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);

You may find it helpful to review the implementations of these methods on the Laravel\Scout\Engines\AlgoliaEngine class. This class will provide you with a good starting point for learning how to implement each of these methods in your own engine.

Registering the Engine

Once you have written your custom engine, you may register it with Scout using the extend method of the Scout engine manager. Scout's engine manager may be resolved from the Laravel service container. You should call the extend method from the boot method of your App\Providers\AppServiceProvider class or any other service provider used by your application:

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;
    });
}

Once your engine has been registered, you may specify it as your default Scout driver in your application's config/scout.php configuration file:

'driver' => 'mysql',

本文章首发在 LearnKu.com 网站上。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
贡献者:3
讨论数量: 0
发起讨论 查看所有版本


暂无话题~