За последние несколько лет в сообществе Laravel приобрели большую популярность поисковые инструменты ElasticSearch и Algolia - мощные средства для индексирования и поиска ваших данных. Бен Корлет проделал невероятную работу, ((https://www.youtube.com/watch?v=waTWeJeFp4A представив ElasticSearch на Laracon Eu 2014)), а я написал ((https://github.com/laravel/laravel.com/pull/18 запрос на включение)) в Laravel написанного мной индексирования для документов на основе ElasticSearch в 2015 году. Но перед тем, как мой запрос был одобрен, люди из Algolia взяли мой код и переделали его на основе Algolia (она быстрее, и у неё лучше пользовательский интерфейс!), и теперь именно этот поиск вы видите в документации Laravel. {{CUT}} Если вы посмотрите на мой или на ((https://github.com/laravel/laravel.com/pull/37 их код)), то поймёте, что интеграция полнотекстового поиска в ваш сайт - не самая простая задача. Позже Algolia выпустили свободный продукт Algolia DocSearch, который позволяет легко ((https://blog.tighten.co/searchable-documentation-for-free-with-jigsaw-and-algolia-docsearch добавить поисковый виджет Algolia)) на страницы с документацией. Но в остальных случаях вам по-прежнему надо писать интеграцию собственноручно - так было до сих пор. == Знакомство с Laravel Scout == Scout - это полнотекстовый поиск на основе драйвера для Eloquent. Scout позволяет легко индексировать и искать содержимое ваших моделей Eloquent. Сейчас он работает с Algolia и ElasticSearch, но Тейлор просит сообщество поучаствовать в реализации поддержки других сервисов полнотекстового поиска. Scout - отдельный пакет Laravel, как Cashier, который вам надо установить с помощью Composer. Мы добавим в наши модели типажи (traits), которые указывают Scout, что он должен слушать события, возникающие при изменении экземпляров этих моделей, и обновлять поисковый индекс. Взгляните на синтаксис полнотекстового поиска любого %%Review%%, содержащего слово %%(t)Llew%%: %% Review::search('Llew')->get(); Review::search('Llew')->paginate(20); Review::search('Llew')->where('account_id', 2)->get(); %% Это требует минимальных настроек. Замечательная вещь. == Установка Scout == Сначала получите пакет (актуальный, с поддержкой приложений Laravel 5.3): %%(sh) composer require laravel/scout %% Затем добавьте сервис-провайдер Scout (%%Laravel\Scout\ScoutServiceProvider::class%%) в раздел %%(t)providers%% в файле %%(t)config/app.php%%. Теперь настроим конфигурацию нашего Scout. Выполните %%(sh)php artisan vendor:publish%% и вставьте свои учётные данные Algolia в %%(t)config/scout.php%%. И наконец, если вы используете Algolia, установите Algolia SDK: %%(sh) composer require algolia/algoliasearch-client-php %% == Маркировка модели для индексирования == Теперь откройте свою модель (для примера мы используем модель книжных обзоров %%Review%%). Импортируйте типаж %%Laravel\Scout\Searchable%%. Вы можете задать доступные для поиска свойства с помощью метода %%toSearchableArray()%% (по умолчанию он соответствует методу %%toArray()%%), и задать имя индекса модели с помощью метода %%searchableAs()%% (по умолчанию это имя таблицы). После этого мы можем зайти и проверить свою страницу индекса Algolia на их сайте. Когда вы добавляете, обновляете или удаляете записи %%Review%%, изменяется ваш индекс Algolia. Вот так просто. == Поиск вашего индекса == Мы уже видели этот пример, но теперь рассмотрим, как выполнять поиск: %% // Получить все записи из 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-команд %%(t)where%%, зато доступен основной функционал проверок сравнения, как вы увидели в приведённых примерах. == Очереди == Вы могли догадаться, что при каждом запросе на изменение записи в БД происходит HTTP-запрос к Algolia. Это может очень быстро замедлить работу приложения, поэтому было бы неплохо выполнять эти операции в очереди. Это довольно просто. В файле %%(t)config/scout.php%% задайте параметру %%(t)queue%% значение %%true%%, тогда обновления будут индексироваться асинхронно. Это так называемая "((ВП:согласованность в конечном счёте==согласованность в конечном счёте))" (eventual consistency) - изменения в записях БД будут происходить немедленно, а обновления поисковых индексов пройдут через очередь так быстро, насколько позволяет ваш обработчик очереди. == Особые случаи == Рассмотрим некоторые особые случаи. === Выполнение операций без индексирования === Если вам надо выполнить набор операций и при этом избежать индексирования, просто оберните их в метод %%withoutSyncingToSearch()%% на вашей модели: %% Review::withoutSyncingToSearch(function () { // например, создать несколько обзоров factory(Review::class, 10)->create(); }); %% === Ручной вызов индексирования в коде === Предположим, вы хотите выполнить индексирование после успешного завершения массовой операции. Как это сделать? Просто добавьте %%searchable()%% в конец любого запроса Eloquent, и он проиндексирует все найденные этим запросом записи: %% Review::all()->searchable(); %% Также вы можете ограничить набор записей для выполнения запроса только теми записями, которые хотите проиндексировать, но стоит отметить, что индексирование вставит новые записи и обновит старые, поэтому будет неплохо запустить его над теми записями, которые могут быть уже проиндексированными. Это работает и с отношениями: %% $user->reviews()->searchable(); %% Также вы можете отменить индексирование любых записей с помощью метода %%unsearchable()%%, используя тот же способ сцепки запросов: %% Review::where('sucky', true)->unsearchable(); %% === Ручной вызов индексирования в командной строке === Вот Artisan-команда для этого: %%(sh) php artisan scout:import App\\Review %% Она возьмёт все модели %%(t)Review%% и проиндексирует их. == Заключение == Вот и всё! Теперь у вас есть полноценный полнотекстовый поиск по вашим моделям Eloquent.