Elastic Scout Driver

repository·master·Indexed 43 days ago

https://github.com/babenkoivan/elastic-scout-driver

An Elasticsearch driver for Laravel Scout that enables advanced search capabilities using Elasticsearch query string syntax. It allows developers to use mini-language syntax (OR, AND, field scoping) within the search() method and provides tools for managing indices, configuring document refresh behavior, and translating Scout Builder instances into Elasticsearch search parameters.

Tokens
2K
Snippets
10
Records
12
Agent score
55%

What's inside Elastic Scout Driver

  1. Prevent indexing empty searchable arrays

    master

    By default, the Elastic driver indexes a model even if toSearchableArray() returns an empty array. To prevent this and ensure models are only indexed when they actually have searchable data, override the shouldBeSearchable method in your model.

    public function shouldBeSearchable()
    {
        return count($this->toSearchableArray()) > 0;
    }
  2. Install Elastic Scout Driver

    master

    To use Elasticsearch with Laravel Scout, you must install both laravel/scout and babenkoivan/elastic-scout-driver via Composer.

    After installation, publish the Scout configuration and update the driver option to elastic in config/scout.php.

    # Install Scout first
    composer require laravel/scout
    
    # Install the Elastic driver
    composer require babenkoivan/elastic-scout-driver
    
    # Publish Scout configuration
    php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
  3. Configure Elasticsearch client settings

    master

    The driver depends on babenkoivan/elastic-client. To customize connection settings (like host, port, or authentication), publish the client configuration file. The resulting file is config/elastic.client.php.

    php artisan vendor:publish --provider="Elastic\Client\ServiceProvider"
  4. Configure document refresh behavior

    master

    You can control whether documents are indexed immediately by configuring the refresh_documents option in config/elastic.scout_driver.php.

    Setting this to true is useful for testing environments where you need search results to be available immediately after indexing. It is false by default.

    php artisan vendor:publish --provider="Elastic\ScoutDriver\ServiceProvider"
  5. Perform basic searches using query string syntax

    master

    The driver uses Elasticsearch query string syntax wrapped in a bool query. This allows you to use mini-language syntax (like OR, AND, and field scoping) directly within the search() method.

    If no query string is provided, the driver performs a match all query while respecting any where constraints.

    // Using query string syntax (e.g., title must contain 'Star' OR 'Trek')
    $orders = App\Order::search('title:(Star OR Trek)')->get();
    
    // Using match all query with constraints
    $orders = App\Order::search()->where('user_id', 1)->get();
  6. Configure document refreshing in the Engine

    master

    The Engine class uses a configuration setting to determine whether to refresh documents immediately after indexing or deleting. This is controlled by the refresh_documents key in your Laravel configuration.

    Set elastic.scout_driver.refresh_documents to true if you need search results to be immediately available after an update or delete operation, though note that this may impact performance.

    // In your config/elastic.php
    'scout_driver' => [
        'refresh_documents' => true,
    ],
  7. Avoid using '_id' in searchable array or metadata

    master

    When preparing models for indexing, ensure that the _id key is not present in the array returned by either toSearchableArray() or scoutMetadata(). The DocumentFactory automatically uses the model's Scout key as the document ID. Including _id in the content will cause an UnexpectedValueException to be thrown.

    To fix this, check your model's toSearchableArray or scoutMetadata methods and remove any _id keys.

    <?php
    
    // Incorrect: This will throw an UnexpectedValueException
    public function toSearchableArray()
    {
        return [
            '_id' => $this->id, // REMOVE THIS
            'name' => $this->name,
        ];
    }
    
    // Correct: The ID is handled automatically
    public function toSearchableArray()
    {
        return [
            'name' => $this->name,
        ];
    }
  8. Manage Elasticsearch indices via the Engine

    master

    The Engine provides methods to manage the lifecycle of Elasticsearch indices directly.

    • createIndex($name, array $options = []): Creates a new index. Note that you cannot change the primaryKey via the $options array; doing so will throw an InvalidArgumentException.
    • deleteIndex($name): Removes the specified index from Elasticsearch.
    • flush($model): Deletes all documents within the index associated with the provided model using a match_all query.
  9. Convert Laravel Scout Builder to Elastic Search Parameters

    master

    The SearchParametersFactory::makeFromBuilder method is used to translate a Laravel Scout Builder instance into an Elastic\Adapter\Search\SearchParameters object. This object contains the structured query, indices, sorting, and pagination required by the Elastic adapter.

    Supported Transformations

    • Indices: Uses the index specified on the builder or falls back to the model's searchableAs() method.
    • Query:
      • If a query string is present, it uses a query_string inside a bool.must clause.
      • If no query is present, it defaults to a match_all query.
    • Filters: Translates Scout wheres, whereIns, and whereNotIns into Elasticsearch filter clauses.
    • Sorting: Maps Scout orders to Elasticsearch sort arrays.
    • Pagination:
      • from is calculated using page and perPage keys in the $options array.
      • size is determined by the perPage key in $options, falling back to the Scout builder's limit.

    Supported Operators for Filters

    When using Scout's where methods, the following operators are mapped to Elasticsearch DSL:

    • = $\rightarrow$ term
    • != $\rightarrow$ bool.must_not with term
    • > $\rightarrow$ range with gt
    • >= $\rightarrow$ range with gte
    • < $\rightarrow$ range with lt
    • <= $\rightarrow$ range with lte
    use Elastic\ScoutDriver\Factories\SearchParametersFactory;
    use Laravel\Scout\Builder;
    
    $factory = new SearchParametersFactory();
    $searchParameters = $factory->makeFromBuilder($scoutBuilder, [
        'page' => 1,
        'perPage' => 15,
    ]);