Weave Code
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

Elasticsearch Bundle Laravel Package

chaplean/elasticsearch-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require chaplean/elasticsearch-bundle
    

    Ensure your project uses Symfony 3.4+ (or 4.x/5.x).

  2. Register Bundle: Add to config/bundles.php (Symfony 4+) or app/AppKernel.php (Symfony 3):

    Chaplean\Bundle\ElasticsearchBundle\ChapleanElasticsearchBundle::class => ['all' => true],
    
  3. Configure Indexes: Define Elasticsearch indexes in config/packages/chaplean_elasticsearch.yaml:

    chaplean_elasticsearch:
        indexes:
            products: 'products_index'  # Maps 'products' service key to 'products_index' in Elasticsearch
            articles: 'articles_index'
    
  4. First Use Case: Inject the ElasticsearchClient service (auto-registered) into a controller/service:

    use Chaplean\Bundle\ElasticsearchBundle\Service\ElasticsearchClient;
    
    class ProductSearchController extends AbstractController
    {
        public function search(ElasticsearchClient $client)
        {
            $index = $client->getIndex('products'); // Resolves to 'products_index'
            $results = $index->search(['query' => ['match_all' => new \stdClass()]]);
            return $this->json($results);
        }
    }
    

Implementation Patterns

Core Workflows

  1. Index Management:

    • Create/Update Index: Use the createIndex() method to define mappings dynamically:
      $index = $client->getIndex('products');
      $index->create([
          'mappings' => [
              'properties' => [
                  'name' => ['type' => 'text'],
                  'price' => ['type' => 'float']
              ]
          ]
      ]);
      
    • Bulk Operations: Leverage the bulk() method for efficient indexing:
      $index->bulk([
          ['index' => ['_id' => 1]],
          ['name' => 'Laptop', 'price' => 999.99],
          ['index' => ['_id' => 2]],
          ['name' => 'Phone', 'price' => 699.99]
      ]);
      
  2. Query Patterns:

    • Basic Search:
      $results = $index->search([
          'query' => [
              'multi_match' => [
                  'query' => 'wireless headphones',
                  'fields' => ['name^3', 'description']
              ]
          ]
      ]);
      
    • Aggregations:
      $results = $index->search([
          'aggs' => [
              'price_ranges' => [
                  'range' => [
                      'field' => 'price',
                      'ranges' => [
                          ['to' => 500],
                          ['from' => 500, 'to' => 1000],
                          ['from' => 1000]
                      ]
                  ]
              ]
          ]
      ]);
      
  3. Integration with Doctrine:

    • Use the ElasticsearchEntityManager to sync Doctrine entities:
      $entityManager = $client->getEntityManager(Product::class);
      $entityManager->persist($product);
      $entityManager->flush(); // Syncs to Elasticsearch
      
    • Note: Requires @Chaplean\Bundle\ElasticsearchBundle\Annotation\Indexed on entities.
  4. Event-Driven Sync:

    • Listen to Doctrine lifecycle events to auto-sync:
      # config/packages/chaplean_elasticsearch.yaml
      chaplean_elasticsearch:
          sync:
              enabled: true
              events: ['postPersist', 'postUpdate', 'postRemove']
      

Gotchas and Tips

Common Pitfalls

  1. Index Naming Collisions:

    • Ensure indexes keys in config are unique and match your Elasticsearch cluster’s naming conventions.
    • Fix: Use descriptive names (e.g., ecommerce_products_v1).
  2. Connection Issues:

    • The bundle uses the elasticsearch/elasticsearch client under the hood.
    • Debug: Check config/packages/chaplean_elasticsearch.yaml for client configuration:
      chaplean_elasticsearch:
          client:
              hosts: ['http://localhost:9200']
              # Add auth if needed:
              # auth: ['username', 'password']
      
    • Tip: Use environment variables for credentials:
      hosts: ['%env(ES_HOST)%']
      
  3. Doctrine Sync Quirks:

    • Annotation Override: If using @Indexed, ensure the entity has a getId() method (Elasticsearch requires _id).
    • Performance: Disable sync during bulk operations or tests:
      chaplean_elasticsearch:
          sync:
              enabled: false
      
  4. Mapping Conflicts:

    • Elasticsearch throws errors if mappings are incompatible (e.g., changing type from text to integer).
    • Solution: Recreate the index or use index->putMapping() carefully.

Debugging Tips

  1. Enable Logging: Add to config/packages/monolog.yaml:

    handlers:
        elasticsearch:
            type: stream
            path: "%kernel.logs_dir%/elasticsearch.log"
            level: debug
    

    Then configure the bundle to log queries:

    chaplean_elasticsearch:
        debug: true
    
  2. Raw Client Access: Access the underlying client for advanced queries:

    $rawClient = $client->getClient();
    $params = $rawClient->indices()->get(['index' => 'products_index']);
    
  3. Testing: Use the ElasticsearchTestCase trait for PHPUnit:

    use Chaplean\Bundle\ElasticsearchBundle\Test\ElasticsearchTestCase;
    
    class ProductSearchTest extends ElasticsearchTestCase
    {
        public function testSearch()
        {
            $this->assertSearchReturns(1, ['query' => ['match_all' => new \stdClass()]]);
        }
    }
    

Extension Points

  1. Custom Index Classes: Extend Chaplean\Bundle\ElasticsearchBundle\Service\Index to add domain-specific methods:

    class ProductIndex extends Index
    {
        public function searchByCategory(string $category)
        {
            return $this->search([
                'query' => [
                    'term' => ['category.keyword' => $category]
                ]
            ]);
        }
    }
    

    Register as a service:

    services:
        app.product_index:
            class: App\Service\ProductIndex
            arguments: ['@chaplean_elasticsearch.client', 'products']
            tags: ['chaplean_elasticsearch.index']
    
  2. Query Builders: Create reusable query DSLs:

    class ProductQueryBuilder
    {
        public function buildSearch(array $filters): array
        {
            $query = ['bool' => ['must' => []]];
            if (isset($filters['price_max'])) {
                $query['bool']['must'][] = ['range' => ['price' => ['lte' => $filters['price_max']]]];
            }
            return ['query' => $query];
        }
    }
    
  3. Async Processing: Use Symfony Messenger to queue Elasticsearch operations:

    $message = new IndexProductMessage($product);
    $this->messageBus->dispatch($message);
    

    Configure the handler to use the ElasticsearchClient.


---
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.
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager