austral/elastic-search-bundle
## Getting Started
### Minimal Setup
1. **Installation**
Add the bundle via Composer:
```bash
composer require austral/elastic-search-bundle
Enable it in config/bundles.php:
Austral\ElasticSearchBundle\AustralElasticSearchBundle::class => ['all' => true],
Configuration
Define Elasticsearch connection in config/packages/austral_elastic_search.yaml:
austral_elastic_search:
clients:
default:
url: 'http://localhost:9200'
options: { /* Elasticsearch client options */ }
First Use Case: Indexing a Model
Annotate your entity with @ElasticSearch and define mappings:
use Austral\ElasticSearchBundle\Annotation\ElasticSearch;
#[ElasticSearch(
index: 'products',
type: 'product',
properties: [
'name' => ['type' => 'text'],
'price' => ['type' => 'float']
]
)]
class Product {}
Sync the index via CLI:
php bin/console austral:elastic-search:sync
Basic Querying
Inject the ElasticSearchClient service and query:
$client = $this->container->get('austral.elastic_search.client');
$results = $client->search('products', [
'query' => ['match' => ['name' => 'laptop']]
]);
CRUD Operations
ElasticSearchManager to sync entities automatically:
$manager = $this->container->get('austral.elastic_search.manager');
$manager->sync($product); // Syncs on save if annotated
$client->delete('products', $product->getId());
Event-Driven Sync
Listen to prePersist, preUpdate, and preRemove events to auto-sync:
// config/services.yaml
services:
App\EventListener\ElasticSearchSyncListener:
tags:
- { name: 'doctrine.event_listener', event: 'prePersist' }
- { name: 'doctrine.event_listener', event: 'preUpdate' }
- { name: 'doctrine.event_listener', event: 'preRemove' }
class ElasticSearchSyncListener {
public function __construct(private ElasticSearchManager $manager) {}
public function prePersist(ObjectManager $om, $entity) {
$this->manager->sync($entity);
}
}
Bulk Operations
Use the BulkProcessor for batch indexing:
$processor = $this->container->get('austral.elastic_search.bulk_processor');
$processor->add('products', $product1, $product2);
$processor->flush();
Aggregations Leverage Elasticsearch aggregations for analytics:
$results = $client->search('products', [
'aggs' => [
'avg_price' => ['avg' => ['field' => 'price']]
]
]);
@ORM\Entity is present.TranslateChildInterface for multilingual fields (e.g., name_en, name_fr).austral_elastic_search:
mappings:
Product:
properties:
slug: { type: 'keyword' }
from and size in queries for pagination:
$client->search('products', [
'from' => 0,
'size' => 10,
'query' => ['match_all' => new \stdClass()]
]);
Index Sync Issues
austral:elastic-search:sync fails silently if the index already exists.--force flag or check index existence first:
php bin/console austral:elastic-search:sync --force
config/packages/austral_elastic_search.yaml:
debug: true
Mapping Conflicts
php bin/console austral:elastic-search:rebuild Product
Event Listener Overhead
Deprecated Methods
isTranslateChild() method was renamed in v3.1.0.implements TranslateChildInterface.austral_elastic_search:
clients:
default:
options:
logger: 'monolog'
validate endpoint:
$client->validate('products', [
'query' => ['match' => ['name' => 'laptop']]
]);
php bin/console austral:elastic-search:status
Custom Processors
Extend AbstractProcessor to add custom logic (e.g., pre-process data before indexing):
class CustomProcessor extends AbstractProcessor {
public function process($document, array $data) {
$data['custom_field'] = strtoupper($data['name']);
return parent::process($document, $data);
}
}
Register in config/services.yaml:
austral_elastic_search:
processors:
custom: App\Processor\CustomProcessor
Custom Commands Create a custom command to extend functionality:
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class CustomElasticCommand extends Command {
protected function execute(InputInterface $input, OutputInterface $output) {
$client = $this->getContainer()->get('austral.elastic_search.client');
// Custom logic here
}
}
Override Mappings
Use mappings config to override default mappings:
austral_elastic_search:
mappings:
Product:
properties:
name:
type: 'text'
analyzer: 'custom_analyzer'
BulkProcessor over individual inserts.$client->indices()->putAlias(['index' => 'products_v2', 'name' => 'products']);
$client->indices()->putSettings('products', [
'index' => ['refresh_interval' => '-1']
]);
```markdown
### Config Quirks
1. **Client Configuration**
- **Issue**: Hardcoded `default` client name may cause confusion.
- **Workaround**: Define multiple clients:
```yaml
austral_elastic_search:
clients:
primary: { url: 'http://primary:9200' }
replica: { url: 'http://replica:9200' }
```
- Access via service ID: `austral.elastic_search.client.primary`.
2. **Annotation Parsing**
- **Issue**: Annotations are parsed at compile time; changes require cache clear:
```bash
php bin/console cache:clear
```
3. **Doctrine Dependency**
- **Issue**: Bundle assumes Doctrine ORM. For non-Doctrine projects, mock `ObjectManager` or use raw arrays.
- **Workaround**: Implement `EntityManagerInterface` manually for custom entities.
4. **Translation Fields**
- **Issue**: Translated fields (e.g., `name_en`) require `TranslateChildInterface` but may not auto-detect.
- **Fix**: Explicitly annotate:
```php
#[ElasticSearch(
properties: [
'name_en' => ['type' => 'text'],
'name_fr' => ['type' => 'text']
]
)]
```
### Pro Tips
- **Use `ElasticSearchManager` for Transactions**
Wrap sync operations in a transaction to ensure data consistency:
```php
$manager = $this->container->get('austral.elastic
How can I help you explore Laravel packages today?