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

Elastica Bundle Laravel Package

friendsofsymfony/elastica-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require friendsofsymfony/elastica-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        FriendsOfSymfony\ElasticaBundle\FriendsOfSymfonyElasticaBundle::class => ['all' => true],
    ];
    
  2. Configure Elasticsearch Connection (config/packages/fos_elastica.yaml):

    fos_elastica:
        clients:
            default: { host: 'localhost', port: 9200 }
        indexes:
            app:
                client: default
                settings:
                    number_of_shards: 3
                    analysis:
                        analyzer:
                            custom_analyzer:
                                type: custom
                                tokenizer: standard
                                filter: [lowercase, asciifolding]
    
  3. First Use Case: Create a simple indexer for a Doctrine entity (e.g., Product):

    # config/packages/fos_elastica.yaml
    fos_elastica:
        indexes:
            app:
                types:
                    product:
                        properties:
                            name: ~
                            price: ~
                        persistence:
                            driver: orm
                            model: App\Entity\Product
                            provider: ~
                            listener: ~
    

    Run the indexer:

    php bin/console fos:elastica:populate
    

Implementation Patterns

Core Workflows

  1. Automatic Indexing with Doctrine: Use listeners to sync Elasticsearch with Doctrine changes:

    fos_elastica:
        indexes:
            app:
                types:
                    product:
                        persistence:
                            listener: true
    
    • Events triggered: onFlush, onFlushClear, postUpdate, postPersist, postRemove.
  2. Custom Indexing Logic: Override the default serializer or transformer for complex objects:

    // src/Elastica/ProductTransformer.php
    namespace App\Elastica;
    
    use App\Entity\Product;
    use Elastica\Transformer\AbstractTransformer;
    
    class ProductTransformer extends AbstractTransformer
    {
        public function transform(Product $product)
        {
            return [
                'name' => $product->getName(),
                'price' => $product->getPrice(),
                'tags' => $product->getTags()->toArray(),
            ];
        }
      }
    

    Configure in fos_elastica.yaml:

    fos_elastica:
        indexes:
            app:
                types:
                    product:
                        persistence:
                            transformer: App\Elastica\ProductTransformer
    
  3. Querying Elasticsearch: Use the repository pattern to query:

    // src/Repository/ProductElasticaRepository.php
    namespace App\Repository;
    
    use FriendsOfSymfony\ElasticaBundle\Repository;
    
    class ProductElasticaRepository extends Repository
    {
        public function findByName($name)
        {
            return $this->createQueryBuilder()
                ->addKeywords('name', $name)
                ->getResults();
        }
    }
    

    Inject and use in services/controllers:

    $products = $this->productElasticaRepository->findByName('laptop');
    

Integration Tips

  1. Hybrid Search (SQL + Elasticsearch): Use Elasticsearch for full-text/fuzzy search and Doctrine for exact matches:

    // Fallback to Doctrine if Elasticsearch returns no results
    $elasticResults = $this->productElasticaRepository->findByName('laptp');
    if (empty($elasticResults)) {
        $doctrineResults = $this->productRepository->findBy(['name' => 'laptp']);
    }
    
  2. Bulk Indexing: Optimize performance with bulk operations:

    php bin/console fos:elastica:populate --batch-size=100
    
  3. Dynamic vs. Static Mapping:

    • Use dynamic mapping for rapid prototyping (let Elasticsearch infer schema).
    • Use static mapping (YAML/XML) for production to enforce consistency.
  4. Partial Updates: Update specific fields without reindexing entire documents:

    $product = $this->productRepository->find($id);
    $product->setPrice(999.99);
    $this->elasticaManager->getIndex('app')->getType('product')->update($product->getId(), [
        'price' => 999.99,
    ]);
    

Gotchas and Tips

Common Pitfalls

  1. Mapping Conflicts:

    • Elasticsearch rejects updates if the document structure doesn’t match the mapping.
    • Fix: Use ?ignore=404 in updates or ensure consistent transformers.
    • Example:
      $this->elasticaManager->getIndex('app')->getType('product')->update($id, $data, ['ignore' => 404]);
      
  2. Listener Overhead:

    • Doctrine listeners can slow down writes if not optimized.
    • Tip: Disable listeners during bulk operations or use fos:elastica:populate directly.
  3. Serializer Mismatches:

    • JMS/Symfony Serializer may not handle circular references or custom types.
    • Fix: Configure the serializer explicitly:
      fos_elastica:
          indexes:
              app:
                  types:
                      product:
                          persistence:
                              serializer: fos_elastica.serializer.symfony
                              groups: ['product']
      
  4. Index Refresh Delay:

    • Elasticsearch buffers changes for performance. Use refresh for immediate visibility:
      $this->elasticaManager->getIndex('app')->refresh();
      

Debugging Tips

  1. Check Index Status:

    php bin/console fos:elastica:status
    
    • Verify mappings, document counts, and health.
  2. Log Elasticsearch Queries: Enable debug mode in config/packages/fos_elastica.yaml:

    fos_elastica:
        clients:
            default:
                logging: true
    
  3. Test Locally with Docker: Use docker.elastic.co/elasticsearch/elasticsearch:8.12.0 for local development:

    # docker-compose.yml
    elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
        environment:
            - discovery.type=single-node
            - xpack.security.enabled=false
        ports:
            - "9200:9200"
    

Extension Points

  1. Custom Indexers: Implement FriendsOfSymfony\ElasticaBundle\Indexer\IndexerInterface for non-Doctrine data sources (e.g., CSV, APIs).

  2. Event Subscribers: Extend indexing logic via events:

    // src/EventSubscriber/ProductIndexSubscriber.php
    namespace App\EventSubscriber;
    
    use Doctrine\Common\EventSubscriber;
    use Doctrine\ORM\Event\LifecycleEventArgs;
    
    class ProductIndexSubscriber implements EventSubscriber
    {
        public function getSubscribedEvents()
        {
            return ['postPersist', 'postUpdate', 'postRemove'];
        }
    
        public function postPersist(LifecycleEventArgs $args)
        {
            $product = $args->getObject();
            // Custom indexing logic
        }
    }
    
  3. Dynamic Index Management: Use the IndexManager to create/drop indexes programmatically:

    $indexManager = $this->elasticaManager->getIndexManager();
    $indexManager->createIndex('app');
    $indexManager->deleteIndex('app');
    
  4. Aggregations: Leverage Elasticsearch aggregations for analytics:

    $queryBuilder = $this->createQueryBuilder();
    $queryBuilder->addAggregation(
        'price_stats',
        'stats',
        'price'
    );
    $results = $queryBuilder->getResults();
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware