Может войдёшь?
Черновики Написать статью Профиль

Знакомство с Laravel Scout

перевод новое в 5.3

За последние несколько лет в сообществе Laravel приобрели большую популярность поисковые инструменты ElasticSearch и Algolia — мощные средства для индексирования и поиска ваших данных. Бен Корлет проделал невероятную работу, представив ElasticSearch на Laracon Eu 2014, а я написал запрос на включение в Laravel написанного мной индексирования для документов на основе ElasticSearch в 2015 году. Но перед тем, как мой запрос был одобрен, люди из Algolia взяли мой код и переделали его на основе Algolia (она быстрее, и у неё лучше пользовательский интерфейс!), и теперь именно этот поиск вы видите в документации Laravel.

Если вы посмотрите на мой или на их код, то поймёте, что интеграция полнотекстового поиска в ваш сайт — не самая простая задача. Позже Algolia выпустили свободный продукт Algolia DocSearch, который позволяет легко добавить поисковый виджет Algolia на страницы с документацией. Но в остальных случаях вам по-прежнему надо писать интеграцию собственноручно — так было до сих пор.

Знакомство с Laravel Scout

Scout — это полнотекстовый поиск на основе драйвера для Eloquent. Scout позволяет легко индексировать и искать содержимое ваших моделей Eloquent. Сейчас он работает с Algolia и ElasticSearch, но Тейлор просит сообщество поучаствовать в реализации поддержки других сервисов полнотекстового поиска.

Scout — отдельный пакет Laravel, как Cashier, который вам надо установить с помощью Composer. Мы добавим в наши модели типажи (traits), которые указывают Scout, что он должен слушать события, возникающие при изменении экземпляров этих моделей, и обновлять поисковый индекс.

Взгляните на синтаксис полнотекстового поиска любого PHPReview, содержащего слово Llew:

PHP
Review::search('Llew')->get();
Review::search('Llew')->paginate(20);
Review::search('Llew')->where('account_id'2)->get();

Это требует минимальных настроек. Замечательная вещь.

Установка Scout

Сначала получите пакет (актуальный, с поддержкой приложений Laravel 5.3):

shcomposer require laravel/scout

Затем добавьте сервис-провайдер Scout (PHPLaravel\Scout\ScoutServiceProvider::class) в раздел providers в файле config/app.php.

Теперь настроим конфигурацию нашего Scout. Выполните shphp artisan vendor:publish и вставьте свои учётные данные Algolia в config/scout.php.

И наконец, если вы используете Algolia, установите Algolia SDK:

shcomposer require algolia/algoliasearch-client-php

Маркировка модели для индексирования

Теперь откройте свою модель (для примера мы используем модель книжных обзоров PHPReview). Импортируйте типаж PHPLaravel\Scout\Searchable. Вы можете задать доступные для поиска свойства с помощью метода PHPtoSearchableArray() (по умолчанию он соответствует методу PHPtoArray()), и задать имя индекса модели с помощью метода PHPsearchableAs() (по умолчанию это имя таблицы).

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

Поиск вашего индекса

Мы уже видели этот пример, но теперь рассмотрим, как выполнять поиск:

PHP
// Получить все записи из Review с термином "Llew"
Review::search('Llew')->get();

// Получить все записи из Review с термином "Llew",
// ограничить вывод по 20 на страницу и читать параметр запроса ?page,
// как в страничном выводе Eloquent
Review::search('Llew')->paginate(20);

// Получить все записи из Review с термином "Llew"
// и значением поля account_id равным 2
Review::search('Llew')->where('account_id'2)->get();

Что вернут эти методы поиска? Коллекцию моделей Eloquent, воссозданных из вашей базы данных. ID хранятся в Algolia, которая возвращает список найденных в результате поиска ID, по ним Scout получает записи из БД и возвращает их в виде объектов Eloquent.

У вас нет всех возможностей SQL-команд where, зато доступен основной функционал проверок сравнения, как вы увидели в приведённых примерах.

Очереди

Вы могли догадаться, что при каждом запросе на изменение записи в БД происходит HTTP-запрос к Algolia. Это может очень быстро замедлить работу приложения, поэтому было бы неплохо выполнять эти операции в очереди. Это довольно просто.

В файле config/scout.php задайте параметру queue значение PHPtrue, тогда обновления будут индексироваться асинхронно. Это так называемая «согласованность в конечном счёте» (eventual consistency) — изменения в записях БД будут происходить немедленно, а обновления поисковых индексов пройдут через очередь так быстро, насколько позволяет ваш обработчик очереди.

Особые случаи

Рассмотрим некоторые особые случаи.

Выполнение операций без индексирования

Если вам надо выполнить набор операций и при этом избежать индексирования, просто оберните их в метод PHPwithoutSyncingToSearch() на вашей модели:

PHP
Review::withoutSyncingToSearch(function () {
  
// например, создать несколько обзоров
  
factory(Review::class, 10)->create();
});

Ручной вызов индексирования в коде

Предположим, вы хотите выполнить индексирование после успешного завершения массовой операции. Как это сделать?

Просто добавьте PHPsearchable() в конец любого запроса Eloquent, и он проиндексирует все найденные этим запросом записи:

PHP
Review::all()->searchable();

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

Это работает и с отношениями:

PHP
$user->reviews()->searchable();

Также вы можете отменить индексирование любых записей с помощью метода PHPunsearchable(), используя тот же способ сцепки запросов:

PHP
Review::where('sucky'true)->unsearchable();

Ручной вызов индексирования в командной строке

Вот Artisan-команда для этого:

shphp artisan scout:import App\\Review

Она возьмёт все модели Review и проиндексирует их.

Заключение

Вот и всё! Теперь у вас есть полноценный полнотекстовый поиск по вашим моделям Eloquent.

Как вы считаете, полезен ли этот материал? Да Нет

Комментарии (2)

Maqsat

Можно ли использовать с версией 5.1

antoha75

Смотрел я Laravel Scout. Не очень убедительная штука. Во-первых, ясно, что Тейлор за Algolia, т.к. она платная и у него конечно есть тут коммерческий интерес. Поддержку Elasticsearch он то добавлял, то исключал, потом опять включал. Есть в его действиях какая-то непоследовательность. Ему даже в твиттере об этом кто-то написал.

Поддержка бесплатного и прекрасного Elasticsearch в Laravel Scout очень ограничена. Например, там нет агрегаций. Вывод такой — вместо использования скаута можно спокойно использовать полнотекстовый поиск mysql. А если нужен серьезный поиск по большой базе, то гораздо лучше поставить стандартный php-клиент от сообщества Elasticsearch, который может реально все!

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.