Laravel Scout
Introduction
Laravel Scout provides a simple, driver based solution for adding full-text search to your Eloquent models. Using model observers, Scout will automatically keep your search indexes in sync with your Eloquent records.
Currently, Scout ships with Algolia and MeiliSearch drivers. In addition, Scout includes a "collection" driver that is designed for local development usage and does not require any external dependencies or third-party services. Furthermore, writing custom drivers is simple and you are free to extend Scout with your own search implementations.
Installation
First, install Scout via the Composer package manager:
composer require laravel/scout
After installing Scout, you should publish the Scout configuration file using the vendor:publish
Artisan command. This command will publish the scout.php
configuration file to your application's config
directory:
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
Finally, add the Laravel\Scout\Searchable
trait to the model you would like to make searchable. This trait will register a model observer that will automatically keep the model in sync with your search driver:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
}
Driver Prerequisites
Algolia
When using the Algolia driver, you should configure your Algolia id
and secret
credentials in your config/scout.php
configuration file. Once your credentials have been configured, you will also need to install the Algolia PHP SDK via the Composer package manager:
composer require algolia/algoliasearch-client-php
MeiliSearch
MeiliSearch is a blazingly fast and open source search engine. If you aren't sure how to install MeiliSearch on your local machine, you may use Laravel Sail, Laravel's officially supported Docker development environment.
When using the MeiliSearch driver you will need to install the MeiliSearch PHP SDK via the Composer package manager:
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
Then, set the SCOUT_DRIVER
environment variable as well as your MeiliSearch host
and key
credentials within your application's .env
file:
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKey
For more information regarding MeiliSearch, please consult the MeiliSearch documentation.
In addition, you should ensure that you install a version of meilisearch/meilisearch-php
that is compatible with your MeiliSearch binary version by reviewing MeiliSearch's documentation regarding binary compatibility.
When upgrading Scout on an application that utilizes MeiliSearch, you should always review any additional breaking changes to the MeiliSearch service itself.
Queueing
While not strictly required to use Scout, you should strongly consider configuring a queue driver before using the library. Running a queue worker will allow Scout to queue all operations that sync your model information to your search indexes, providing much better response times for your application's web interface.
Once you have configured a queue driver, set the value of the queue
option in your config/scout.php
configuration file to true
:
'queue' => true,
Configuration
Configuring Model Indexes
Each Eloquent model is synced with a given search "index", which contains all of the searchable records for that model. In other words, you can think of each index like a MySQL table. By default, each model will be persisted to an index matching the model's typical "table" name. Typically, this is the plural form of the model name; however, you are free to customize the model's index by overriding the searchableAs
method on the model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
/**
* Get the name of the index associated with the model.
*
* @return string
*/
public function searchableAs()
{
return 'posts_index';
}
}
Configuring Searchable Data
By default, the entire toArray
form of a given model will be persisted to its search index. If you would like to customize the data that is synchronized to the search index, you may override the toSearchableArray
method on the model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
/**
* Get the indexable data array for the model.
*
* @return array
*/
public function toSearchableArray()
{
$array = $this->toArray();
// Customize the data array...
return $array;
}
}
Configuring The Model ID
By default, Scout will use the primary key of the model as 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.
*
* @return mixed
*/
public function getScoutKey()
{
return $this->email;
}
/**
* Get the key name used to index the model.
*
* @return mixed
*/
public function getScoutKeyName()
{
return 'email';
}
}
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 this 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.
Local Development
While you are free to use the Algolia or MeiliSearch 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 or MeiliSearch indexes, is unnecessary when using the collection 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:
/**
* Modify the query used to retrieve models when making all of the models searchable.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function makeAllSearchableUsing($query)
{
return $query->with('author');
}
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();