Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Elastic Adapter Laravel Package

babenkoivan/elastic-adapter

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require babenkoivan/elastic-adapter
    

    Requires elasticsearch/elasticsearch (≥7.0) as a dependency.

  2. Basic Configuration:

    use Babenkoivan\ElasticAdapter\ElasticAdapter;
    
    $adapter = new ElasticAdapter([
        'hosts' => ['http://localhost:9200'],
        'index' => 'your_index_name',
    ]);
    
  3. First Use Case:

    // Index a document
    $adapter->index([
        'id' => 'doc1',
        'title' => 'Sample Document',
        'content' => 'This is a test document.',
    ]);
    
    // Search documents
    $results = $adapter->search(['match' => ['title' => 'Sample']]);
    

Where to Look First

  • ElasticAdapter class: Core functionality for CRUD operations.
  • ElasticSearchBuilder: For complex queries (see usage examples).
  • ElasticAdapterException: Handle errors gracefully.

Implementation Patterns

Common Workflows

  1. CRUD Operations:

    // Create/Update
    $adapter->index($document, $id); // $id optional (auto-generated if omitted)
    
    // Read
    $document = $adapter->get('doc1');
    
    // Update (partial)
    $adapter->update('doc1', ['status' => 'published']);
    
    // Delete
    $adapter->delete('doc1');
    
  2. Search Patterns:

    // Basic match query
    $results = $adapter->search(['match' => ['title' => 'Laravel']]);
    
    // Bool query with filters
    $results = $adapter->search([
        'bool' => [
            'must' => ['match' => ['content' => 'tutorial']],
            'filter' => ['term' => ['status' => 'published']],
        ],
    ]);
    
    // Pagination
    $results = $adapter->search($query, ['from' => 0, 'size' => 10]);
    
  3. Bulk Operations:

    $adapter->bulk([
        ['index' => ['_id' => '1']],
        ['title' => 'Bulk Doc 1'],
        ['index' => ['_id' => '2']],
        ['title' => 'Bulk Doc 2'],
    ]);
    

Integration with Laravel

  1. Service Provider Binding:

    // config/app.php
    'providers' => [
        \Babenkoivan\ElasticAdapter\ElasticAdapterServiceProvider::class,
    ],
    
    // config/elastic.php
    'default' => 'elasticsearch',
    'connections' => [
        'elasticsearch' => [
            'hosts' => ['http://localhost:9200'],
            'index' => 'app_documents',
        ],
    ],
    
  2. Facade Usage:

    use Illuminate\Support\Facades\Elastic;
    
    Elastic::index(['title' => 'Hello', 'content' => 'World']);
    
  3. Eloquent Model Integration (Custom):

    use Babenkoivan\ElasticAdapter\Eloquent\Scopes\ElasticScope;
    
    class Post extends Model
    {
        public function scopeSearch($query, $searchTerm)
        {
            return $query->addGlobalScope(new ElasticScope(function ($model, $builder) use ($searchTerm) {
                $results = Elastic::search(['match' => ['title' => $searchTerm]]);
                return $builder->whereIn('id', array_pluck($results['hits'], 'id'));
            }));
        }
    }
    
  4. Event Listeners:

    // Sync Eloquent model to Elasticsearch on save
    Post::saved(function ($post) {
        Elastic::index($post->toArray(), $post->id);
    });
    

Gotchas and Tips

Pitfalls

  1. Index Mapping Conflicts:

    • If your documents have dynamic fields (e.g., tags), Elasticsearch may auto-detect mappings. To avoid surprises, define explicit mappings upfront:
      $adapter->putMapping([
          'properties' => [
              'title' => ['type' => 'text', 'analyzer' => 'english'],
              'tags' => ['type' => 'keyword'],
          ],
      ]);
      
  2. Idempotent Operations:

    • index() will overwrite documents if the _id exists. Use create() (if supported) or check existence first:
      if (!$adapter->exists('doc1')) {
          $adapter->index($document, 'doc1');
      }
      
  3. Connection Timeouts:

    • Default timeouts may be too short for large operations. Configure in the adapter:
      $adapter = new ElasticAdapter([
          'hosts' => ['http://localhost:9200'],
          'timeout' => 30, // seconds
      ]);
      
  4. Bulk Operation Limits:

    • Elasticsearch has a bulk request limit (~10MB or 1,000 operations). Split large bulk operations:
      $chunkSize = 500;
      foreach (array_chunk($documents, $chunkSize) as $chunk) {
          $adapter->bulk($chunk);
      }
      

Debugging

  1. Enable Logging:

    $adapter = new ElasticAdapter([
        'hosts' => ['http://localhost:9200'],
        'logger' => new \Monolog\Logger('elasticsearch'),
    ]);
    

    Or use Laravel’s log:

    'logger' => \Illuminate\Support\Facades\Log::class,
    
  2. Raw Response Inspection:

    $response = $adapter->search($query, [], true); // $raw = true
    dd($response);
    
  3. Common Errors:

    • Elasticsearch\Common\Exceptions\Missing404Exception: Document/index not found. Verify IDs/indices.
    • Elasticsearch\Common\Exceptions\BadRequest400Exception: Invalid query syntax. Use Elasticsearch Query DSL Analyzer to debug.

Tips

  1. Use ElasticSearchBuilder for Complex Queries:

    $query = (new ElasticSearchBuilder())
        ->match('title', 'Laravel')
        ->boolShould([
            ['term' => ['status' => 'published']],
            ['range' => ['price' => ['gte' => 10]]],
        ])
        ->getQuery();
    $results = $adapter->search($query);
    
  2. Leverage Laravel’s Caching: Cache frequent search results:

    $cacheKey = "elastic_results_{$searchTerm}";
    $results = Cache::remember($cacheKey, now()->addHours(1), function () use ($adapter, $searchTerm) {
        return $adapter->search(['match' => ['title' => $searchTerm]]);
    });
    
  3. Async Indexing: Use Laravel Queues for non-critical indexing:

    Post::saved(function ($post) {
        dispatch(new IndexPostInElastic($post));
    });
    
  4. Schema Validation: Validate documents before indexing:

    use Illuminate\Validation\Validator;
    
    $validator = Validator::make($document, [
        'title' => 'required|string|max:255',
        'content' => 'required|string',
    ]);
    
    if ($validator->fails()) {
        throw new \InvalidArgumentException($validator->errors()->first());
    }
    
  5. Alias Management: Use aliases for zero-downtime reindexing:

    $adapter->createAlias('alias_name', 'old_index');
    $adapter->createAlias('alias_name', 'new_index', ['is_write_index' => true]);
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings