Installation
composer require friendsofsymfony/elastica-bundle
Enable the bundle in config/bundles.php:
return [
// ...
FriendsOfSymfony\ElasticaBundle\FOSElasticaBundle::class => ['all' => true],
];
Basic Configuration
Configure Elasticsearch client in config/packages/fos_elastica.yaml:
fos_elastica:
clients:
default: { host: '%env(ELASTICSEARCH_HOST)%', port: '%env(ELASTICSEARCH_PORT)%' }
indexes:
app:
client: default
settings:
number_of_shards: 3
number_of_replicas: 0
types:
product:
properties:
name: ~
price: ~
First Use Case: Indexing a Doctrine Entity
Annotate your entity (e.g., Product):
use FriendsOfSymfony\ElasticaBundle\Annotation as Elastica;
/**
* @Elastica\Document(repositoryClass="App\Repository\ProductElasticaRepository")
*/
class Product {}
Define a repository:
namespace App\Repository;
use FriendsOfSymfony\ElasticaBundle\Repository;
class ProductElasticaRepository extends Repository {}
Index data via CLI:
php bin/console fos:elastica:populate
Automatic Indexing with Doctrine Events
Leverage listeners for postPersist, postUpdate, and postRemove:
# config/packages/fos_elastica.yaml
fos_elastica:
listeners:
product:
type: App\Entity\Product
events:
- onFlush
- onClear
Manual Indexing Use the repository to index/unindex entities:
$product = $entityManager->find(Product::class, 1);
$repository->index($product); // Index
$repository->remove($product); // Unindex
Querying Elasticsearch
$query = $repository->createQuery()
->select('p')
->where('p.name', 'partial', 'search_term')
->setLimit(10);
$results = $repository->find($query);
Dynamic Mapping Skip configuration and rely on Elasticsearch’s dynamic mapping:
fos_elastica:
indexes:
app:
types:
dynamic_product: ~ # No properties defined
fos_elastica.serializer to customize serialization:
fos_elastica:
serializer:
groups: ['default', 'elasticsearch']
fos_elastica:
indexes:
app:
types:
product:
properties:
slug: { type: keyword }
fos:elastica:populate for large datasets:
php bin/console fos:elastica:populate --batch-size=100
Doctrine vs. Elasticsearch Data Mismatch
@Elastica\Property to override:
/**
* @Elastica\Property(type="integer")
*/
private $price;
php bin/console fos:elastica:info
Listener Overhead
fos_elastica:
listeners:
product: { events: [] } # Disable listeners
Index Naming Conflicts
app_<entity>. Customize via:
fos_elastica:
indexes:
app:
alias: { app_products: product }
Serialization Issues
@Groups or @Exclude:
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\Exclude()
*/
private $sensitiveData;
php bin/console fos:elastica:info
config/packages/dev/fos_elastica.yaml:
fos_elastica:
debug: true
docker.elastic.co/elasticsearch/elasticsearch:7.15.0).Custom Indexers
Extend FOSElasticaBundle\Indexer\IndexerInterface for custom logic:
class CustomIndexer implements IndexerInterface {
public function index($document, $indexName, $typeName) { ... }
}
Register in services:
services:
App\Indexer\CustomIndexer:
tags: [fos_elastica.indexer]
Event Subscribers
Listen to fos_elastica.index or fos_elastica.remove events:
use FriendsOfSymfony\ElasticaBundle\Event\IndexEvent;
class MySubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [IndexEvent::INDEX => 'onIndex'];
}
public function onIndex(IndexEvent $event) { ... }
}
Custom Query Builders
Extend FOSElasticaBundle\Query\QueryBuilder for domain-specific queries:
class ProductQueryBuilder extends QueryBuilder {
public function filterByCategory($category) { ... }
}
Bind to repository:
class ProductElasticaRepository extends Repository {
protected function createQueryBuilder() {
return new ProductQueryBuilder($this);
}
}
How can I help you explore Laravel packages today?