27/05/2016 - ELASTICSEARCH, SYMFONY
Default listener
settings of FOSElasticaBundle is set to automatically update elasticsearch index in real time when an object is added, updated or removed. It is set as listener: ~
in the config file. If you want to manually update elasticsearch index then you can use example below.
In this example, there is a 'Post' entity and we will do insert, update and delete operations with doctrine then manually update elasticsearch index with an event subscriber.
Note: Rather than using this version, I would suggest you to use shorter event listener version that I have in this blog.
fos_elastica:
clients:
default: { host: 127.0.0.1, port: 9200 }
indexes:
post_index:
client: default
index_name: post_dev
types:
post:
mappings:
id:
type: integer
index: not_analyzed
title:
type: string
analyzer: english
year:
type: integer
index: not_analyzed
price:
type: double
index: not_analyzed
is_published:
type: boolean
index: not_analyzed
persistence:
driver: orm
model: Application\SearchBundle\Entity\Post
finder: ~
provider: ~
listener: ~
namespace Application\SearchBundle\Service;
...........
...........
class PostDatabaseService
{
...........
...........
public function createPost()
{
$post = new Post();
$post->setTitle('inanzzz');
$post->setYear(1999);
$post->setPrice(6.99);
$post->setIsPublished(true);
$this->entityManager->persist($post);
$this->entityManager->flush();
return sprintf('create-post ID: %s', $post->getId());
}
public function updatePost($id)
{
/** @var Post $post */
$post = $this->findPost($id);
$post->setTitle('inanzzz inanzzz');
$this->entityManager->flush();
return sprintf('update-post ID: %s', $id);
}
public function deletePost($id)
{
/** @var Post $post */
$post = $this->findPost($id);
$this->entityManager->remove($post);
$this->entityManager->flush();
return sprintf('delete-post ID: %s', $id);
}
private function findPost($id)
{
$post = $this->postRepository->findOneById($id);
if (!$post instanceof Post) {
throw new EntityNotFoundException(sprintf('Post [%s] cannot be found.', $id));
}
return $post;
}
}
You should also study vendor/friendsofsymfony/elastica-bundle/Doctrine/Listener.php
class to see how things actually work.
namespace Application\SearchBundle\Subscriber;
use Application\SearchBundle\Entity\Post;
use Doctrine\Common\EventSubscriber;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use FOS\ElasticaBundle\Persister\ObjectPersisterInterface;
use FOS\ElasticaBundle\Provider\IndexableInterface;
class PostIndexSubscriber implements EventSubscriber
{
/** @var ObjectPersisterInterface */
private $postPersister;
/** @var IndexableInterface */
private $indexable;
private $events;
private $config;
private $scheduledForInsert;
private $scheduledForUpdate;
private $scheduledForDelete;
public function __construct(
ObjectPersisterInterface $postPersister,
IndexableInterface $indexable,
array $events,
array $config
) {
$this->postPersister = $postPersister;
$this->indexable = $indexable;
$this->events = $events;
$this->config = $config;
}
public function getSubscribedEvents()
{
return $this->events;
}
public function postPersist(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof Post) {
if ($this->postPersister->handlesObject($entity)) {
if ($this->isObjectIndexable($entity)) {
$this->scheduledForInsert = $entity;
}
}
}
}
public function postUpdate(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof Post) {
if ($this->postPersister->handlesObject($entity)) {
if ($this->isObjectIndexable($entity)) {
$this->scheduledForUpdate = $entity;
}
}
}
}
public function preRemove(LifecycleEventArgs $args)
{
$entity = $args->getObject();
if ($entity instanceof Post) {
if ($this->postPersister->handlesObject($entity)) {
$this->scheduledForDelete = $entity->getId();
}
}
}
public function postFlush()
{
if ($this->scheduledForInsert) {
$this->postPersister->insertOne($this->scheduledForInsert);
$this->scheduledForInsert = null;
}
if ($this->scheduledForUpdate) {
$this->postPersister->replaceOne($this->scheduledForUpdate);
$this->scheduledForUpdate = null;
}
if ($this->scheduledForDelete) {
$this->postPersister->deleteById($this->scheduledForDelete);
$this->scheduledForDelete = null;
}
}
private function isObjectIndexable($object)
{
return $this->indexable->isObjectIndexable(
$this->config['index'],
$this->config['type'],
$object
);
}
}
services:
application_search.subscriber.post_index:
class: Application\SearchBundle\Subscriber\PostIndexSubscriber
arguments:
- @fos_elastica.object_persister.post_index.post
- @fos_elastica.indexable
- [ postPersist, postUpdate, preRemove, postFlush ]
- { index: post_index, type: post }
tags:
- { name: doctrine.event_subscriber }