jackardios/es-scout-driver

Advanced Elasticsearch driver for Laravel Scout with full Query DSL support

Installs: 5

Dependents: 1

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/jackardios/es-scout-driver

dev-main 2026-02-10 19:04 UTC

This package is auto-updated.

Last update: 2026-02-10 19:11:46 UTC


README

Latest Version on Packagist
PHP Version
CI License: MIT

Advanced Elasticsearch driver for Laravel Scout with full Query DSL support.

Features

  • Full Elasticsearch Query DSL support
  • Fluent API for building complex queries
  • Bool queries with must, should, filter, mustNot
  • Full-text queries: match, multi_match, match_phrase, query_string
  • Term-level queries: term, terms, range, exists, prefix, wildcard, regexp, fuzzy, ids
  • Geo queries: geo_distance, geo_bounding_box, geo_shape
  • Compound queries: bool, nested, function_score, dis_max, boosting, constant_score
  • Joining queries: has_child, has_parent, parent_id
  • Aggregations: terms, avg, sum, min, max, stats, cardinality, histogram, date_histogram, range
  • Sorting with multiple options
  • Highlighting
  • Suggestions
  • Pagination with cursor support
  • Multi-index search
  • Soft deletes support

Requirements

  • PHP 8.1+
  • Laravel 10, 11, or 12
  • Elasticsearch 8.x or 9.x

Installation

composer require jackardios/es-scout-driver

Publish the configuration files:

php artisan vendor:publish --provider="Jackardios\EsScoutDriver\ServiceProvider"

Configure your Elasticsearch connection in .env:

SCOUT_DRIVER=elastic

ELASTIC_HOST=localhost:9200

Quick Start

1. Add the Searchable trait to your model

use Jackardios\EsScoutDriver\Searchable;

class Book extends Model
{
    use Searchable;

    public function toSearchableArray(): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'author' => $this->author,
            'price' => $this->price,
            'published_at' => $this->published_at,
        ];
    }
}

2. Create your index (optional but recommended)

For index management, we recommend babenkoivan/elastic-migrations:

composer require babenkoivan/elastic-migrations
php artisan elastic:make:migration create_books_index
php artisan elastic:migrate

Note: The config/elastic.client.php is compatible with elastic-migrations.

3. Index your data

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

4. Search

use Jackardios\EsScoutDriver\Support\Query;

// Simple search
$books = Book::searchQuery(Query::match('title', 'laravel'))->execute();

// Complex search with bool query
$books = Book::searchQuery()
    ->must(Query::match('title', 'laravel'))
    ->filter(Query::term('status', 'published'))
    ->filter(Query::range('price')->gte(10)->lte(50))
    ->sort('published_at', 'desc')
    ->size(20)
    ->execute();

// Get models
$models = $books->models();

// Get total count
$total = $books->total;

Basic Usage

Match Query

Book::searchQuery(Query::match('title', 'elasticsearch'))->execute();

// With options
Book::searchQuery(
    Query::match('title', 'elasticsearch')
        ->fuzziness('AUTO')
        ->operator('and')
)->execute();

Multi-Match Query

Book::searchQuery(
    Query::multiMatch(['title', 'description'], 'search text')
        ->type('best_fields')
        ->fuzziness('AUTO')
)->execute();

Bool Query

Book::searchQuery()
    ->must(Query::match('title', 'laravel'))
    ->must(Query::match('description', 'framework'))
    ->should(Query::term('featured', true))
    ->filter(Query::range('price')->lte(100))
    ->mustNot(Query::term('status', 'draft'))
    ->execute();

Range Query

Book::searchQuery(
    Query::range('price')->gte(10)->lte(50)
)->execute();

// Date range
Book::searchQuery(
    Query::range('published_at')
        ->gte('2024-01-01')
        ->lte('now')
        ->format('yyyy-MM-dd')
)->execute();

Sorting

use Jackardios\EsScoutDriver\Sort\Sort;

Book::searchQuery(Query::matchAll())
    ->sort('price', 'asc')
    ->sort('_score', 'desc')
    ->execute();

// Advanced sorting
Book::searchQuery(Query::matchAll())
    ->sort(Sort::field('price')->desc()->missing('_last'))
    ->sort(Sort::score())
    ->execute();

Pagination

// Standard pagination
$paginator = Book::searchQuery(Query::matchAll())
    ->paginate(perPage: 15, pageName: 'page', page: 1);

// Access in Blade
@foreach ($paginator->models() as $book)
    {{ $book->title }}
@endforeach

{{ $paginator->links() }}

Aggregations

use Jackardios\EsScoutDriver\Aggregations\Agg;

$result = Book::searchQuery(Query::matchAll())
    ->aggregate('avg_price', Agg::avg('price'))
    ->aggregate('by_author', Agg::terms('author')->size(10))
    ->execute();

// Get aggregation results
$avgPrice = $result->aggregationValue('avg_price');
$authorBuckets = $result->buckets('by_author');

Highlighting

$result = Book::searchQuery(Query::match('title', 'laravel'))
    ->highlight('title', preTags: ['<em>'], postTags: ['</em>'])
    ->highlight('description')
    ->execute();

foreach ($result->hits() as $hit) {
    $highlights = $hit->highlight; // ['title' => ['<em>Laravel</em> Guide']]
}

Documentation

License

MIT License. See LICENSE for details.