Installation:
composer require friendsofsymfony/elastica-bundle
For Symfony Flex, use the recipe.
Configure Elasticsearch Connection (config/packages/fos_elastica.yaml):
fos_elastica:
clients:
default: # Client name
host: '%env(ELASTICSEARCH_HOST)%'
port: '%env(ELASTICSEARCH_PORT)%'
user: '%env(ELASTICSEARCH_USER)%'
password: '%env(ELASTICSEARCH_PASSWORD)%'
client_config:
ssl: true
client_options:
retries: 3
Define an Index (config/packages/fos_elastica.yaml):
fos_elastica:
indexes:
app_product: # Index name
types: # Document types
Product:
properties:
name: ~
price: ~
persistence:
driver: orm
model: App\Entity\Product
provider: ~
listener: ~
First Use Case: Populate the index via CLI:
php bin/console fos:elastica:populate
Or programmatically:
$this->container->get('fos_elastica.finder.app_product')->findAll();
fos_elastica.yaml for clients, indexes, and mappings.fos:elastica:* commands for index management (e.g., populate, reset, reindex).postPersist, postUpdate, postRemove) for automatic indexing.Automatic Indexing (via Doctrine listeners):
fos_elastica:
indexes:
app_product:
types:
Product:
persistence:
driver: orm
listener: true # Enable automatic indexing
postPersist, postUpdate, and postRemove events.Manual Indexing:
$product = new Product();
$this->get('fos_elastica.object_persister.app_product')->persist($product);
Basic Search:
$finder = $this->get('fos_elastica.finder.app_product');
$results = $finder->find(['name' => 'Laptop']);
Paginated Search (using Pagerfanta):
$finder = $this->get('fos_elastica.finder.app_product');
$paginator = $finder->findPaginated(['name' => 'Laptop'], 1, 10);
Aggregations:
$results = $finder->find(['aggregations' => ['price_avg' => ['avg' => ['field' => 'price']]]]);
Define custom mappings in fos_elastica.yaml:
fos_elastica:
indexes:
app_product:
types:
Product:
properties:
name:
type: text
analyzer: custom_analyzer
price:
type: float
scale: 2
Use Symfony Messenger for background indexing:
fos_elastica:
indexes:
app_product:
types:
Product:
persistence:
driver: orm
listener: true
async: true # Enable async indexing
Manage aliases for zero-downtime reindexing:
fos_elastica:
indexes:
app_product:
alias: product_index
settings:
analysis:
analyzer:
custom_analyzer:
type: custom
tokenizer: standard
filter: [lowercase, asciifolding]
Doctrine ORM Integration:
listener: true in persistence config for automatic sync.fos_elastica.doctrine.orm_listener for event-driven indexing.Symfony Serializer:
fos_elastica:
serializer:
groups: [default, elastica]
Custom Transformers:
FOS\ElasticaBundle\Transformer\TransformerInterface to customize object-to-array conversion:
class CustomProductTransformer implements TransformerInterface
{
public function transform($object, array $context = [])
{
return [
'name' => $object->getName(),
'price' => $object->getPrice(),
'tags' => $object->getTags()->toArray(),
];
}
}
services:
App\Transformer\CustomProductTransformer:
tags: [fos_elastica.transformer, { alias: 'app_product', type: 'Product' }]
Event Subscribers:
PostElasticaRequestEvent or ElasticaRequestExceptionEvent for query logging/debugging:
use FOS\ElasticaBundle\Event\PostElasticaRequestEvent;
class ElasticaSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return [
PostElasticaRequestEvent::NAME => 'onPostRequest',
];
}
public function onPostRequest(PostElasticaRequestEvent $event)
{
$request = $event->getRequest();
$this->logger->info('Elastica Query:', ['query' => $request->getBody()]);
}
}
Testing:
fos_elastica.test.client for in-memory testing:
$client = $this->get('fos_elastica.test.client');
$index = $client->getIndex('test_index');
$index->create();
Configuration Changes:
hosts array instead of host, port, url).Dynamic vs. Static Mappings:
fos_elastica:
indexes:
app_product:
settings:
mapping:
dynamic: strict
Index Aliases:
fos:elastica:reindex with --alias flag:
php bin/console fos:elastica:reindex --alias=product_index --from=app_product_old --to=app_product_new
Performance:
batch_size in fos:elastica:populate:
php bin/console fos:elastica:populate --batch-size=100
Serializer Groups:
#[Groups(['elastica'])]
private $name;
Doctrine Events:
listener: true does not remove existing Doctrine listeners. Manually clear them if needed:
$this->get('fos_elastica.doctrine.orm_listener')->disable();
Elasticsearch Version Mismatch:
Enable Query Logging:
fos_elastica:
client:
debug: '%kernel.debug%'
Logs queries to var/log/dev.log (or prod.log in production if debug: true).
Check Index Status:
php bin/console fos:elastica:status
Reindex Safely:
--dry-run to preview changes:
php bin/console fos:elastica:reindex --dry-run
How can I help you explore Laravel packages today?