Поддержите проект сделав пожертвование.
Поделитесь своим кодом и идеями!
Поделитесь своим кодом и идеями!

Laravel Scout

Введение

Laravel Scout предоставляет простое решение на основе драйверов для добавления полнотекстового поиска в ваши модели Eloquent. Используя наблюдателей (observers) моделей, Scout будет автоматически синхронизировать поисковые индексы с данными моделей Eloquent.

В настоящее время Scout поставляется с драйверами Algolia, Meilisearch, Typesense и MySQL / PostgreSQL (database) . Кроме того, Scout включает поисковый драйвер «коллекций», предназначенный для использования в локальной разработке и не требующий каких-либо внешних зависимостей или сторонних сервисов. Кроме того, написать собственные драйверы просто, и вы можете свободно расширять Scout своими собственными реализациями поиска.

Установка

Сначала установите Scout через менеджер пакетов Composer:

composer require laravel/scout

После установки Scout вы должны опубликовать файл конфигурации Scout с помощью Artisan-команды vendor:publish. Эта команда добавит файл конфигурации scout.php в каталог config вашего приложения:

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

Наконец, добавьте трейт (trait) Laravel\Scout\Searchable к модели, которую вы хотите сделать доступной для поиска. Этот трейт зарегистрирует наблюдателя модели, который будет автоматически синхронизировать модель с вашим драйвером поиска:

<?php

namespace App\Models;

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

class Post extends Model
{
    use Searchable;
}

Использование очереди

Хотя не обязательно использовать Scout с настройками очередей, рекомендуется настроить драйвер очереди перед использованием библиотеки. Запуск рабочего процесса очереди позволит Scout помещать все операции, синхронизирующие информацию модели с поисковыми индексами, в очередь, что обеспечит более быстрое время ответа для веб-интерфейса вашего приложения.

После настройки драйвера очереди установите значение параметра queue в вашем конфигурационном файле config/scout.php в 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 вы должны настроить учетные данные Algolia id и secret в файле конфигурации config/scout.php. После того как ваши учетные данные будут настроены, вам также необходимо будет установить Algolia PHP SDK через диспетчер пакетов Composer:

composer require algolia/algoliasearch-client-php

Meilisearch

Meilisearch это невероятно быстрая поисковая система с открытым исходным кодом. Если вы не знаете, как установить Meilisearch на свой локальный компьютер, вы можете использовать Laravel Sail, официально поддерживаемую Laravel среду разработки Docker.

При использовании драйвера Meilisearch вам необходимо установить Meilisearch PHP SDK через менеджер пакетов Composer:

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

Затем установите переменную среды SCOUT_DRIVER, а также учетные данные вашего Meilisearch host и key в файле .env вашего приложения:

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

Для получения дополнительной информации обратитесь к документации MeiliSearch.

Кроме того, вы должны убедиться, что вы установили версию meilisearch/meilisearch-php которая совместима с вашей двоичной версией Meilisearch, просмотрев документацию Meilisearch относительно двоичной совместимости.

При обновлении Scout в приложении, которое использует MeiliSearch, вы всегда должны просматривать любые дополнительные критические изменения в самой службе Meilisearch.

Typesense

Typesense – это быстрый и открытый поисковый движок, поддерживающий поиск по ключевым словам, семантический поиск, гео-поиск и векторный поиск.

Вы можете разместить Typesense у себя или использовать Typesense Cloud.

Чтобы начать использовать Typesense с Scout, установите Typesense PHP SDK через менеджер пакетов Composer:

composer require typesense/typesense-php

Затем установите переменную среды SCOUT_DRIVER, а также укажите адрес вашего Typesense и ключ API в файле .env вашего приложения:

SCOUT_DRIVER=typesense
TYPESENSE_API_KEY=masterKey
TYPESENSE_HOST=localhost

При необходимости вы также можете указать порт, путь и протокол вашей установки:

TYPESENSE_PORT=8108
TYPESENSE_PATH=
TYPESENSE_PROTOCOL=http

Дополнительные настройки и определения схемы для коллекций Typesense можно найти в конфигурационном файле вашего приложения config/scout.php. Для получения дополнительной информации о Typesense, пожалуйста, обратитесь к документации Typesense.

Подготовка данных для хранения в Typesense

При использовании Typesense ваши модели для поиска должны определить метод toSearchableArray, который преобразует основной ключ вашей модели в строку и дату создания в метку времени UNIX:

/**
 * Получить индексируемый массив данных для модели.
 *
 * @return array<string, mixed>
 */
public function toSearchableArray()
{
    return array_merge($this->toArray(),[
        'id' => (string) $this->id,
        'created_at' => $this->created_at->timestamp,
    ]);
}

Вы также должны определить схемы коллекций Typesense в файле конфигурации вашего приложения config/scout.php. Схема коллекции описывает типы данных каждого поля, которые можно искать с помощью Typesense. Для получения дополнительной информации о всех доступных параметрах схемы обратитесь к документации Typesense.

Если вам необходимо изменить схему коллекции Typesense после её определения, вы можете либо выполнить команды scout:flush и scout:import, которые удалят все существующие индексированные данные и создадут схему заново. Либо вы можете использовать API Typesense для изменения схемы коллекции без удаления каких-либо индексированных данных.

Если ваша модель для поиска поддерживает мягкое удаление, вы должны определить поле __soft_deleted в схеме соответствующей модели Typesense в файле конфигурации вашего приложения config/scout.php.

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

Настройка поисковых данных

По умолчанию вся форма 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();

        // 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 требует предварительного определения настроек поиска индекса, таких как фильтруемые атрибуты, сортируемые атрибуты и другие поддерживаемые поля настроек.

Фильтруемые атрибуты – это любые атрибуты, по которым вы планируете фильтровать при вызове метода where Scout, в то время как сортируемые атрибуты – это любые атрибуты, по которым вы планируете сортировать при вызове метода orderBy Scout. Чтобы определить настройки вашего индекса, отредактируйте раздел index-settings в записи meilisearch в файле конфигурации scout вашего приложения:

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'],
        ],
    ],
],

Если модель, лежащая в основе определенного индекса, поддерживает мягкое удаление и включена в массив index-settings, Scout автоматически включит поддержку фильтрации для мягко удаленных моделей в этом индексе. Если у вас нет других атрибутов, по которым можно фильтровать или сортировать для определения индекса модели с мягким удалением, вы можете просто добавить пустую запись в массив index-settings для этой модели:

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

После настройки параметров индекса вашего приложения необходимо вызвать команду Artisan scout:sync-index-settings. Эта команда сообщит Meilisearch о ваших текущих настройках индекса. Для удобства вы можете включить эту команду в ваш процесс развертывания:

php artisan scout:sync-index-settings

Настройка идентификатора модели

По умолчанию Scout будет использовать первичный ключ модели в качестве уникального идентификатора / ключа модели, который хранится в поисковом индексе. Если вам нужно настроить это поведение, вы можете переопределить методы getScoutKey и getScoutKeyName в модели:

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

    /**
     * Переопределение имени ключа индекса модели по умолчанию
     */
    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');
    }
}

Идентификация пользователей

Scout также позволяет автоматически идентифицировать пользователей при использовании Algolia. Связывание аутентифицированного пользователя с операциями поиска может быть полезно при просмотре аналитики поиска на панели инструментов Algolia. Вы можете включить идентификацию пользователя, определив для переменной среды SCOUT_IDENTIFY значение true в файле .env вашего приложения:

SCOUT_IDENTIFY=true

Включение этой функции также передаст IP-адрес запроса и основной идентификатор вашего аутентифицированного пользователя в Algolia, поэтому эти данные будут связаны с любым поисковым запросом, сделанным пользователем.

Драйвер базы данных/колекции

Драйвер базы данных

В настоящее время драйвер базы данных поддерживает MySQL и PostgreSQL.

Если ваше приложение взаимодействует с небольшими или средними базами данных или имеет легкую нагрузку, вам может быть удобнее начать с драйвера “database” Scout. Драйвер будет использовать запросы “where like” и полнотекстовые индексы при фильтрации результатов из вашей существующей базы данных для определения применимых результатов поиска для вашего запроса.

Чтобы использовать драйвер базы данных, вы можете просто установить значение переменной среды SCOUT_DRIVER равным database, или указать драйвер database непосредственно в конфигурационном файле scout вашего приложения:

SCOUT_DRIVER=database

Как только вы укажете драйвер базы данных в качестве предпочтительного, вам необходимо настроить свои данные для поиска. Затем вы можете начать выполнять поисковые запросы к вашим моделям. Некоторые поисковые движки, такие как Algolia, Meilisearch или Typesense, требуют предворительную индексацию. При использовании баз данных индексация не требуется

Настройка стратегий поиска в базе данных

По умолчанию драйвер базы данных будет выполнять запрос “where like” к каждому атрибуту модели, который вы настроили для поиска. Однако в некоторых ситуациях это может привести к низкой производительности. Поэтому стратегия поиска может быть настроена так, чтобы некоторые столбцы использовали запросы полнотекстового поиска или только условия “where like” для поиска префиксов строк (пример%) вместо поиска внутри всей строки (%пример%).

Чтобы определить это поведение, вы можете назначить атрибуты PHP методу toSearchableArray вашей модели. Любые столбцы, которым не назначены дополнительные стратегии поиска, будут продолжать использовать стратегию “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 или указать драйвер collection непосредственно в файле конфигурации scout вашего приложения:

SCOUT_DRIVER=collection

После того как вы указали драйвер коллекции в качестве предпочтительного, вы можете начать выполнение поисковых запросов по вашим моделям. Индексирование поисковой системой, необходимое для заполнения индексов Algolia или MeiliSearch, не требуется при использовании драйвера коллекций.

Отличия от Движка Базы Данных

На первый взгляд, драйверы “database” и “collections” достаточно похожи. Оба они взаимодействуют непосредственно с вашей базой данных для получения результатов поиска. Однако драйвер “collections” не использует полнотекстовые индексы или LIKE операторы для поиска соответствующих записей. Вместо этого он извлекает все возможные записи и использует вспомогательную функцию Str::is Laravel для определения того, существует ли строка поиска в значениях атрибутов модели.

Драйвер “collections” является наиболее портативным, так как он работает с любыми реляционными базами данных, поддерживаемыми Laravel (включая SQLite и SQL Server); однако он менее эффективен, чем драйвер базы данных.

Индексирование

Пакетный импорт

Если вы устанавливаете Scout в существующий проект, возможно, у вас уже есть записи базы данных, которые необходимо импортировать в индексы. Scout предоставляет Artisan-команду scout:import, которую вы можете использовать для импорта всех существующих записей в поисковые индексы:

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

Команду flush можно использовать для удаления всех записей из поисковых индексов:

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

Изменение запроса на импорт

Если вы хотите изменить запрос, который используется для получения моделей для пакетного импорта, вы можете определить метод makeAllSearchableUsing в модели. Это отличное место для добавления любых отношений, которые могут потребоваться перед импортом:

use Illuminate\Database\Eloquent\Builder;

/**
 * Измените запрос, сделав поиск по всем моделям.
 */
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();

Вы также можете вызвать метод searchable для экземпляра коллекции Eloquent:

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

Или, если у вас уже есть коллекция Eloquent, вы можете вызвать метод searchable для коллекции, чтобы добавить экземпляры моделей в их соответствующий индекс:

$orders->searchable();

Метод searchable можно считать операцией “upsert”. Другими словами, если запись модели уже есть в поисковом индексе, то она будет обновлена. Если записи нет, она будет добавлена в индекс.

Обновление записей

Чтобы обновить поисковый индекс модели, вам нужно только обновить свойства экземпляра модели и вызвать метод save для сохранения в базе данных. Scout автоматически сохранит изменения в поисковом индексе:

use App\Models\Order;

$order = Order::find(1);

// Update the order...

$order->save();

Вы также можете вызвать метод searchable` в экземпляре запроса Eloquent, чтобы обновить коллекцию моделей. Если моделей нет в поисковом индексе, они будут созданы:

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

Если вы не хотите извлекать модель перед удалением записи, вы можете использовать метод unsearchable для экземпляра запроса Eloquent:

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

Если вы хотите удалить записи поискового индекса для всех моделей в коллекции, вы можете вызвать метод unsearchable на цепочке вызова:

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

Или, если у вас уже есть коллекция Eloquent, вы можете вызвать метод unsearchable для коллекции, чтобы удалить экземпляры моделей из индекса:

$orders->unsearchable();

Приостановка индексации

Иногда вам может потребоваться выполнить некоторые операции Eloquent с моделью без синхронизации данных модели с поисковым индексом. Вы можете сделать это, используя метод withoutSyncingToSearch. Этот метод принимает замыкание, которое будет немедленно выполнено. Любые операции модели, которые происходят внутри замыкания, не будут синхронизироваться с индексом модели:

use App\Models\Order;

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

Экземпляры моделей с условным поиском

Иногда может потребоваться сделать модель доступной для поиска только при определенных условиях. Например, представьте, что у вас есть модель App\Models\Post, которая может находиться в одном из двух состояний: «черновик» и «опубликована». Вы можете добавлять в поисковый индекс только «опубликованные» сообщения. Для этого необходимо определить в модели метод shouldBeSearchable:

/**
 * Определите, когда модель должна быть доступной для поиска.
 */
public function shouldBeSearchable(): bool
{
    return $this->isPublished();
}

Метод shouldBeSearchable применяется только при манипуляциях с моделями с помощью методов save, create, запросов или в цепочке вызовов. Непосредственное добавление моделей или коллекций в поисковый индекс с помощью метода searchable переопределит результат метода shouldBeSearchable.

Метод shouldBeSearchable не применим при использовании драйвера “database” в Scout, так как все данные для поиска всегда хранятся в базе данных. Для достижения аналогичного поведения при использовании драйвера базы данных следует использовать Условия 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();

Пользовательский индекс

Поисковые запросы обычно выполняются по индексу, указанному в методе searchchableAs модели. Однако вы можете использовать метод within, чтобы указать индекс, который следует использовать вместо этого:

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

Условия Where

Scout позволяет добавлять в поисковые запросы простые условия “where” (“где”). В настоящее время эти условия поддерживают только базовые проверки числового равенства и в первую очередь полезны для определения области поисковых запросов по идентификатору владельца. Поскольку поисковый индекс не является реляционной базой данных, более сложные условия “where” в настоящее время не поддерживаются:

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, вам необходимо настроить фильтруемые атрибуты вашего приложения перед использованием условий “where” Scout.

Постраничная разбивка данных (Pagination) (Пагинация)

Помимо получения коллекции моделей, вы можете разбить результаты поиска на страницы, используя метод 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.

Псевдоудаление

Если ваши проиндексированные модели псевдоудалены и вам нужно выполнить поиск по своим псевдоудаленным моделям, установите параметр soft_delete в файле config/scout.php на true:

'soft_delete' => true,

Когда этот параметр имеет значение true, Scout не будет удалять псевдоудаленные модели из поискового индекса. Вместо этого он установит скрытый атрибут __soft_deleted для проиндексированной записи. Затем вы можете использовать методы withTrashed или onlyTrashed для получения псевдоудаленных записей при поиске:

use App\Models\Order;

// Использовать удаленные записи при получении результатов ...
$orders = Order::search('Star Trek')->withTrashed()->get();

// Использовать только удаленные записи при получении результатов ...
$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();

Поскольку это обратный вызов вызывается после того, как соответствующие модели уже были извлечены из поискового движка вашего приложения, метод query не следует использовать для “фильтрации” результатов. Вместо этого вы должны использовать условия where Scout.

Настройка Запроса Результатов 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();

Разработка поискового движка

Реализация своего поискового механизма

Если одна из встроенных поисковых систем 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. Вы должны вызвать метод extend из метода boot вашего класса App\Providers\AppServiceProvider или любого другого провайдера, используемого вашим приложением:

use App\ScoutExtensions\MySqlSearchEngine;
use Laravel\Scout\EngineManager;

/**
 * Загрузка сервисов приложения.
 */
public function boot(): void
{
    resolve(EngineManager::class)->extend('mysql', function () {
        return new MySqlSearchEngine;
    });
}

После регистрации движка вы можете указать его в качестве driver по умолчанию в файле конфигурации config/scout.php:

'driver' => 'mysql',