Laravel Scout
11.x
.
Почему это важно?
Введение
Laravel Scout предоставляет простое решение на основе драйверов для добавления полнотекстового поиска в ваши Eloquent-модели. С помощью наблюдателей за моделями Scout будет автоматически синхронизировать ваши поисковые индексы с вашими записями Eloquent.
Сейчас Scout поставляется с драйвером Algolia; однако, написать свой драйвер довольно просто и вы можете дополнить Scout своей собственной реализацией поиска.
Установка
Сначала установите Scout через менеджер пакетов Composer:
composer require laravel/scout
Затем добавьте ScoutServiceProvider
в массив providers
вашего конфига config/app.php
:
Laravel\Scout\ScoutServiceProvider::class,
После регистрации сервис-провайдера Scout опубликуйте его конфигурацию с помощью Artisan-команды vendor:publish
. Эта команда опубликует файл настроек scout.php
в ваш каталог config
:
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
И наконец, добавьте трейт Laravel\Scout\Searchable
в модель, которую хотите сделать доступной для поиска. Этот трейт зарегистрирует наблюдателя модели, чтобы синхронизировать модель с вашим драйвером поиска:
<?php
namespace App;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Searchable;
}
Очередь
Вам нужно изучить настройку драйвера очереди перед использованием этой библиотеки, не смотря на то, что использовать очереди в Scout не обязательно. После запуска обработчика очереди Scout сможет ставить в очередь все операции синхронизации информации вашей модели с вашими поисковыми индексами, обеспечивая намного лучшее время отклика для веб-интерфейса вашего приложения.
После настройки драйвера очереди задайте значение true
параметру queue
в конфиге config/scout.php
:
'queue' => true,
Условия для работы драйвера
Algolia
При использовании драйвера Algolia задайте ваши учётные данные Algolia id
и secret
в своем конфиге config/scout.php
. После этого установите Algolia PHP SDK через менеджер пакетов Composer:
composer require algolia/algoliasearch-client-php
Настройка
Настройка индексов модели
Каждая модель Eloquent синхронизируется с заданным поисковым “индексом”, который содержит все записи для поиска этой модели. Другими словами, можно представить каждый индекс как таблицу MySQL. По-умолчанию для каждой модели будет назначен индекс, совпадающий с именем “таблицы” модели. Как правило, это множественная форма имени модели, но вы можете изменить индекс модели, переопределив для неё метод searchableAs
:
<?php
namespace App;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Searchable;
/**
* Получить имя индекса для модели.
*
* @return string
*/
public function searchableAs()
{
return 'posts_index';
}
}
Настройка данных для поиска
По-умолчанию в индексе модели будут все её данные, аналогично результату toArray
. Если вы хотите настроить то, какие данные будут синхронизироваться с поисковым индексом, переопределите метод модели toSearchableArray
:
<?php
namespace App;
use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use Searchable;
/**
* Получить индексируемый массив данных для модели.
*
* @return array
*/
public function toSearchableArray()
{
$array = $this->toArray();
// Customize array...
return $array;
}
}
Индексирование
Пакетный импорт
Если вы устанавливаете Scout в существующий проект, у вас уже могут быть записи БД, которые вам надо импортировать в ваш драйвер поиска. Scout предоставляет Artisan-команду import
, которую можно использовать для импорта всех существующих записей в ваши поисковые индексы:
php artisan scout:import "App\Post"
Добавление записей
После добавления в модель типажа Laravel\Scout\Searchable
вам остаётся только сохранить (save
) экземпляр модели, и она автоматически добавится в поисковый индекс. Если вы настроили Scout на использование очередей, то эта операция будет выполнена в фоне вашим обработчиком очереди:
$order = new App\Order;
// ...
$order->save();
Добавление через запрос
Если вы хотите добавить коллекцию моделей в свой поисковый индекс через запрос Eloquent, вы можете добавить метод searchable
к запросу Eloquent. Метод searchable
разделит на части результаты запроса и добавит записи в ваш поисковый индекс. Если вы настроили Scout на использование очередей, то все части будут добавлены в фоне обработчиками очереди:
// Добавление через запрос Eloquent...
App\Order::where('price', '>', 100)->searchable();
// Вы также можете добавить записи через отношения...
$user->orders()->searchable();
// Вы также можете добавить записи через коллекции...
$orders->searchable();
Метод searchable
можно рассматривать как операцию “upsert” (обновить или вставить). Другими словами, если запись модели уже в вашем индексе, она будет обновлена. А если её нет в поисковом индексе, то она будет добавлена в него.
Обновление записей
Для обновления модели, предназначенной для поиска, вам надо обновить только свойства экземпляра модели и сохранить (save
) модель в БД. Scout автоматически внесёт изменения в ваш поисковый индекс:
$order = App\Order::find(1);
// Обновить заказ...
$order->save();
Вы также можете использовать метод searchable
на запросе Eloquent для обновления коллекции моделей. Если моделей нет в поисковом индексе, они будут созданы:
// Обновление через запрос Eloquent...
App\Order::where('price', '>', 100)->searchable();
// Вы также можете обновить через отношения...
$user->orders()->searchable();
// Вы также можете обновить через коллекции...
$orders->searchable();
Удаление записей
Для удаления записи из индекса просто удалите (delete
) модель из БД. Этот способ удаления совместим даже с мягко удаляемыми моделями:
$order = App\Order::find(1);
$order->delete();
Если вам не надо получать модель перед удалением записи, используйте метод unsearchable
на экземпляре запроса Eloquent или коллекции:
// Удаление через запрос Eloquent...
App\Order::where('price', '>', 100)->unsearchable();
// Также вы можете удалять через отношения...
$user->orders()->unsearchable();
// Также вы можете удалять через коллекции...
$orders->unsearchable();
Приостановка индексирования
Иногда бывает необходимо выполнить на модели группу операций Eloquent, при этом не синхронизируя данные модели с поисковым индексом. Это можно сделать методом withoutSyncingToSearch
. Этот метод принимает единственную анонимную функцию, которая будет выполнен немедленно. Все операции на модели, сделанные в функции, не будут синхронизированы с индексом модели:
App\Order::withoutSyncingToSearch(function () {
// Выполнение действий над моделью...
});
Поиск
Вы можете начать поиск модели методом search
. Он принимает единственную строку, которая используется для поиска для поиска моделей. Затем вам надо добавить метод get
к поисковому запросу для получения моделей Eloquent, которые будут найдены по этому запросу:
$orders = App\Order::search('Star Trek')->get();
Поскольку поиски Scout возвращают коллекцию моделей Eloquent, вы можете вернуть результаты даже напрямую из роута или контроллера и они будут автоматически конвертированы в JSON:
use Illuminate\Http\Request;
Route::get('/search', function (Request $request) {
return App\Order::search($request->search)->get();
});
Если вы бы хотели получить необработанные результаты прежде, чем они будут сконвертированы в модели Eloquent, следует использовать метод raw
:
$orders = App\Order::search('Star Trek')->raw();
Поисковые запросы, как правило, будут выполняться в индексе, указываемом методом модели searchableAs
method. Однако, вы можете использовать метод within
, чтобы указать собственный индекс:
$orders = App\Order::search('Star Trek')
->within('tv_shows_popularity_desc')
->get();
Условия Where
Scout позволяет добавлять простые условия “where” в ваши поисковые запросы. На данный момент эти условия поддерживают только базовые числовые сравнения на равенство и в основном полезны для ограничения поисковых запросов определённым ID. Поскольку поисковые индексы не являются реляционной БД, то более сложные условия “where” пока не поддерживаются:
$orders = App\Order::search('Star Trek')->where('user_id', 1)->get();
Страничный вывод
Помимо получения коллекции моделей вы можете разделить результаты поиска на страницы методом paginate
. Этот метод вернёт экземпляр Paginator
, как и в случае страничного вывода обычного запроса Eloquent:
$orders = App\Order::search('Star Trek')->paginate();
Вы можете указать, сколько моделей необходимо размещать на одной странице, передав количество первым аргументом методу paginate
:
$orders = App\Order::search('Star Trek')->paginate(15);
Когда вы получите результаты, вы можете отобразить их и вывести страничные ссылки с помощью Blade, как и в случае страничного вывода обычного запроса Eloquent:
<div class="container">
@foreach ($orders as $order)
{{ $order->price }}
@endforeach
</div>
{{ $orders->links() }}
Пользовательские движки
Создание движка
Если ни один из встроенных поисковых движков 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 map($results, $model);
Вам может быть полезно посмотреть на реализацию этих методов в классе Laravel\Scout\Engines\AlgoliaEngine
. Этот класс предоставит вам хорошую отправную точку для изучения того, как реализуется каждый из этих методов.
Регистрация движка
После создания своего движка вы можете зарегистрировать его в Scout с помощью метода extend
менеджера движков Scout. Вам надо вызвать метод extend
из метода boot
вашего AppServiceProvider
или любого другого сервис-провайдера в вашем приложении. Например, если вы создали MySqlSearchEngine
, зарегистрируйте его так:
use Laravel\Scout\EngineManager;
/**
* Начальная загрузка всех сервисов приложения.
*
* @return void
*/
public function boot()
{
resolve(EngineManager::class)->extend('mysql', function () {
return new MySqlSearchEngine;
});
}
После регистрации движка вы можете указать его в качестве драйвера (driver
) Scout по-умолчанию в конфиге config/scout.php
:
'driver' => 'mysql',