Elastic Scout Driver Plus

repository·master·Indexed 43 days ago

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

An extension for Elastic Scout Driver that adds advanced Elasticsearch features to Laravel Scout. It provides support for aggregations, highlighting, custom routing, multiple connections, multi-index search via join(), and complex boolean queries using a dedicated Query builder or raw arrays.

Tokens
18.3K
Snippets
90
Records
91
Agent score
55%

What's inside Elastic Scout Driver Plus

  1. Build boolean queries with Query::bool()

    master

    You can construct complex Elasticsearch boolean queries using the Elastic\ScoutDriverPlus\Support\Query::bool() method. This method allows you to compose multiple query clauses (like must, filter, should, etc.) to refine your search results. Once the query is built, you can execute it using the model's searchQuery($query)->execute() method.

    $query = Query::bool()->must(
        Query::match()
            ->field('title')
            ->query('The Book')
    );
    
    $searchResult = Book::searchQuery($query)->execute();
  2. Paginate search results

    master

    You can paginate results using the paginate(int $perPage) method. The resulting paginator implements the same interface as SearchResult (allowing access to models(), highlights(), etc.).

    By default, the driver paginates hits. You can change the pagination target using onlyModels() or onlyDocuments():

    • Paginate hits (default): Iterating over the paginator yields hit objects.
    • Paginate models: Use ->onlyModels() to iterate directly over Eloquent models.
    • Paginate documents: Use ->onlyDocuments() to iterate directly over document objects.

    Note: When using paginate(), the from and size parameters are ignored.

    // paginate hits (default)
    $paginator = Book::searchQuery($query)->paginate(10);
    foreach ($paginator as $hit) {
        $model = $hit->model();
    }
    
    // paginate models
    $paginator = Book::searchQuery($query)
        ->paginate(10)
        ->onlyModels();
    
    foreach ($paginator as $model) {
        $id = $model->id;
    }
    
    // paginated documents
    $paginator = Book::searchQuery($query)
        ->paginate(10)
        ->onlyDocuments();
    
    foreach ($paginator as $document) {
        $id = $document->id();
    }
  3. Install Elastic Scout Driver Plus

    master

    Install the library via Composer.

    Prerequisites: This library requires Elastic Scout Driver to function. It is recommended to update your existing babenkoivan/elastic-scout-driver installation before proceeding.

    Steps:

    1. Install the package:
      composer require babenkoivan/elastic-scout-driver-plus
    2. Update the base driver (if already installed):
      composer update babenkoivan/elastic-scout-driver
    3. Update your models: Replace the standard Laravel\Scout\Searchable trait with Elastic\ScoutDriverPlus\Searchable in all models you wish to index using this driver.
    composer require babenkoivan/elastic-scout-driver-plus
  4. Execute a search with parameters

    master

    Once a query is defined, use the searchQuery method on your model to initiate a search builder. You can then chain parameters like size(), sort(), or highlight() to refine the request before calling execute() to retrieve the results.

    Example Workflow:

    1. Define the query.
    2. Call Model::searchQuery($query).
    3. Chain parameters (e.g., size, sort).
    4. Call execute() to get the SearchResult object.
    // 1. Define query
    $query = Query::match()->field('title')->query('My book');
    
    // 2. Build and refine search
    $builder = Book::searchQuery($query)
        ->size(2)
        ->sort('price', 'asc');
    
    // 3. Execute
    $searchResult = $builder->execute();
  5. Construct search queries with SearchParametersBuilder

    master

    The SearchParametersBuilder is used to fluently construct complex Elasticsearch queries. It allows you to define query logic, sorting, pagination, aggregations, and more before executing the search against your models. You typically start by obtaining a builder instance from a searchable model and then chain methods to configure the search parameters.

    // Assuming $model is a searchable Eloquent model
    $results = $model->search()
        ->query(['match' => ['title' => 'search term']])
        ->sort('created_at', 'desc')
        ->size(20)
        ->execute();
  6. Define nested queries using builders or raw arrays

    master

    The searchQuery() method accepts both the fluent Query builder and raw Elasticsearch query arrays for nested structures.

    // Using the Query builder
    $query = Query::nested()
        ->path('author')
        ->query(Query::match()->field('author.name')->query('Steven'));
    
    // Using a raw query array
    $query = [
        'nested' => [
            'path' => 'author',
            'query' => [
                'match' => [
                   'author.name' => 'Steven'
                ]
            ]
        ]
    ];
    
    $searchResult = Book::searchQuery($query)->execute();
  7. Access hits from SearchResult

    master

    The hits() method returns a collection of hits. Each hit object provides metadata about the match and links to the underlying data. You can also retrieve the raw representation of a specific hit.

    $hit = $hits->first();
    
    $indexName = $hit->indexName();
    $score = $hit->score();
    $model = $hit->model();
    $document = $hit->document();
    $highlight = $hit->highlight();
    $innerHits = $hit->innerHits();
    $explanation = $hit->explanation();
    
    $raw = $hit->raw();
  8. Use filter clauses in boolean queries

    master

    The filter clause requires documents to match the specified criteria, but unlike must, it does not contribute to the relevance score. You can pass either a Query builder instance or a raw array to the filter() method.

    If you need to pass a raw array directly and replace any existing filter clauses, use filterRaw().

    // Using the builder
    $filter = Query::term()
        ->field('published')
        ->value('2020-06-07');
    
    $query = Query::bool()->filter($filter);
    
    // Using a raw array
    $filter = [
        'term' => [
            'published' => '2020-06-07'
        ]
    ];
    $query = Query::bool()->filter($filter);
    
    // Using filterRaw (replaces existing filter clause)
    $query = Query::bool()->filterRaw([
        'term' => [
            'published' => '2020-06-07'
        ]
    ]);
    
    $searchResult = Book::searchQuery($query)->execute();
  9. Use matchPhrase() for exact phrase matching

    master

    Use Elastic\ScoutDriverPlus\Support\Query::matchPhrase() to match documents that contain the exact provided phrase.

    Available methods:

    • field(string $field): Specify the field to search.
    • query(string $query): Set the text to find.
    • analyzer(string $analyzer): Specify the analyzer to convert query text into tokens.
    • slop(int $slop): Define the maximum number of positions allowed between matching tokens.
    • zeroTermsQuery(string $zeroTermsQuery): Define what to return if the analyzer removes all tokens.
    $query = Query::matchPhrase()
        ->field('title')
        ->query('My book');
    
    $searchResult = Book::searchQuery($query)->execute();
  10. Optimize indexing with Eager Loading Relations

    master

    When indexing models, you can include related data in the toSearchableArray() method. To prevent N+1 query issues during bulk indexing, override the searchableWith() method to specify which relations should be eager-loaded.

    class Book extends Model
    {
        use Elastic\ScoutDriverPlus\Searchable;
    
        public function toSearchableArray()
        {
            return [
                'title' => $this->title,
                'price' => $this->price,
                'author' => $this->author->only(['name', 'phone_number']),
            ];
        }
    
        public function searchableWith()
        {
            return ['author'];
        }
    }
  11. Set minimumShouldMatch in boolean queries

    master

    The minimumShouldMatch method allows you to specify the number of should queries a document must match to be included in the results.

    $query = Query::bool()
        ->should(Query::term()->field('published')->value('2018-04-23'))
        ->should(Query::term()->field('published')->value('2020-03-07'))
        ->minimumShouldMatch(1);
    
    $searchResult = Book::searchQuery($query)->execute();