Search by

jackardios / es-scout-driver

jackardios

Advanced Elasticsearch driver for Laravel Scout with full Query DSL support

Package info

github.com/Jackardios/es-scout-driver

pkg:composer/jackardios/es-scout-driver

Statistics

Installs: 465

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0-rc.1 2026-09-29 21:38 UTC

This package is auto-updated.

Last update: 2026-09-30 02:31:08 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.2+ (Laravel 13 requires 8.3+)
  • Laravel 12 or 13
  • Laravel Scout 10.24+ or 11
  • Elasticsearch 8.x or 9.x

Laravel 10 and 11 are supported by the 0.x line: composer require jackardios/es-scout-driver:^0.1.

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() }}

perPage must be greater than 0, and page must be greater than or equal to 1.

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

Backward Compatibility

From 1.0.0 the package follows Semantic Versioning. Breaking changes to the public API ship only in a new major version.

The public API is every public class, method, constant and property not marked @internal: Searchable, SearchBuilder, SearchResult, Hit, Suggestion, Paginator, SearchCursor, the Query, Agg and Sort factories and the classes they return, the enums, the exceptions and the configuration files.

  • QueryInterface, AggregationInterface, SortInterface and EngineInterface may be implemented outside the package. New methods are added to them only in a major version.
  • SearchBuilder may be extended. Its protected members come from @internal traits and are not covered.
  • Engine is final: to change engine behaviour, implement EngineInterface or wrap the engine.
  • The Query\Concerns and Aggregations\Concerns traits are not covered: their methods belong to the public API of the classes that use them, but using a trait in your own class may break in a minor release.
  • @internal code (the engine helpers, model resolution, the fromRaw() factories, the Paginator and SearchCursor constructors and every SearchResult constructor argument after $raw) may change in any release.

License

MIT License. See LICENSE for details.