Laravel Scout

Use Sigmie as a Laravel Scout driver — index Eloquent models in Elasticsearch with typo tolerance, highlighting, facets, and custom analyzers.

On this page

sigmie/elasticsearch-scout is a Laravel Scout driver. It plugs into Scout’s model lifecycle so writes and deletes flow into Elasticsearch automatically, and Model::search() runs through Sigmie’s search builder.

Install

Install Scout first:

composer require laravel/scout

Publish its config:

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

Install the Sigmie driver:

composer require sigmie/elasticsearch-scout

Set the Scout driver in your .env:

SCOUT_DRIVER=elasticsearch

Publish the Sigmie config (optional, for customization):

php artisan vendor:publish --provider="Sigmie\ElasticsearchScout\ElasticsearchScoutServiceProvider"

This creates config/elasticsearch-scout.php:

return [
'hosts' => env('ELASTICSEARCH_HOSTS', '127.0.0.1:9200'),
'auth' => [
'type' => env('ELASTICSEARCH_AUTH_TYPE', 'none'),
'user' => env('ELASTICSEARCH_USER', ''),
'password' => env('ELASTICSEARCH_PASSWORD', ''),
'token' => env('ELASTICSEARCH_TOKEN', ''),
'headers' => [],
],
'guzzle_config' => [
'allow_redirects' => false,
'http_errors' => false,
'connect_timeout' => 15,
],
'index-settings' => [
'shards' => env('ELASTICSEARCH_INDEX_SHARDS', 1),
'replicas' => env('ELASTICSEARCH_INDEX_REPLICAS', 2),
],
];

Make a model searchable

Use Sigmie’s Searchable trait instead of Laravel Scout’s. They have the same name; the Sigmie version adds the methods Sigmie needs:

use Sigmie\ElasticsearchScout\Searchable;
use Sigmie\Mappings\NewProperties;
 
class Movie extends Model
{
use Searchable;
 
public function elasticsearchProperties(NewProperties $properties): void
{
$properties->title('title');
$properties->name('director');
$properties->category('genre');
$properties->date('created_at');
$properties->date('updated_at');
}
}

elasticsearchProperties() is required — it defines the index schema for this model.

Build the index

php artisan scout:index "App\Models\Movie"

Import existing rows

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

Update the index settings

Unlike other Scout drivers, Sigmie requires the model name when re-syncing:

php artisan scout:sync-index-settings "App\Models\Movie"

This re-applies your elasticsearchProperties() and elasticsearchIndex() configuration.

Customize the search

Define elasticsearchSearch() to use any NewSearch feature:

use Sigmie\Search\NewSearch;
 
class Movie extends Model
{
use Searchable;
 
public function elasticsearchProperties(NewProperties $props): void
{
$props->title('title');
$props->name('director');
$props->category('genre');
}
 
public function elasticsearchSearch(NewSearch $search): void
{
$search->typoTolerance();
$search->typoTolerantAttributes(['title', 'director']);
$search->retrieve(['title', 'director']);
$search->fields(['title', 'director']);
$search->highlighting(
['title', 'director'],
'<span class="font-bold">',
'</span>',
);
}
}

For one-off customization, pass a closure to Model::search():

use Sigmie\Search\NewSearch;
 
Movie::search('Star Wars', function (NewSearch $search) {
$search->weight(['title' => 5]);
})->get();

Customize index analysis

use Sigmie\Index\NewIndex;
 
class Movie extends Model
{
use Searchable;
 
public function elasticsearchProperties(NewProperties $props): void { /* ... */ }
public function elasticsearchSearch(NewSearch $search): void { /* ... */ }
 
public function elasticsearchIndex(NewIndex $index): void
{
$index->tokenizeOnWordBoundaries()
->lowercase()
->trim()
->shards(3)
->replicas(3);
}
}

If you don’t define elasticsearchIndex(), Sigmie defaults to tokenizing on word boundaries, lowercase, trim.

Accessing hit metadata

Each model returned by Scout carries the raw Elasticsearch hit on $model->hit:

$movie = Movie::search('Star Wars')->get()->first();
 
$movie->hit['_score']; // 32.343453
$movie->hit['highlight']['title'][0]; // <span class="font-bold">Star Wars</span>

Date formatting

Sigmie expects dates in Y-m-d H:i:s.u. Laravel’s default toSearchableArray converts Eloquent timestamps automatically; if you override toSearchableArray(), do the conversion yourself:

public function toSearchableArray(): array
{
$array = $this->toArray();
 
$array['created_at'] = $this->created_at?->format('Y-m-d H:i:s.u');
$array['updated_at'] = $this->updated_at?->format('Y-m-d H:i:s.u');
 
return $array;
}

Or use a different format and tell Sigmie about it:

public function elasticsearchProperties(NewProperties $props): void
{
$props->date('created_at')->format('MM/dd/yyyy');
$props->date('updated_at')->format('MM/dd/yyyy');
}

Authentication

Basic auth

ELASTICSEARCH_AUTH_TYPE=basic
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASSWORD=your-password

Bearer token

ELASTICSEARCH_AUTH_TYPE=token
ELASTICSEARCH_TOKEN=your-token-here

Custom headers

If you need API keys or custom auth headers, populate 'headers' in config/elasticsearch-scout.php:

'headers' => [
'X-App-Token' => env('APP_TOKEN'),
'Authorization' => 'ApiKey ' . env('ELASTICSEARCH_API_KEY'),
],

Multiple hosts

ELASTICSEARCH_HOSTS=10.0.0.1:9200,10.0.0.2:9200,10.0.0.3:9200

Guzzle configuration

Tune the underlying HTTP client in config/elasticsearch-scout.php:

'guzzle_config' => [
'allow_redirects' => false,
'http_errors' => false,
'connect_timeout' => 15,
'timeout' => 30,
],

See Connection Setup for the full list of Guzzle options Sigmie understands.

See also

  • Search — every option available in elasticsearchSearch().
  • Mappings & Properties — types available in elasticsearchProperties().
  • Indices — analysis options for elasticsearchIndex().
  • Laravel AI SDK — expose Scout-indexed models as AI agent tools.