Use identifiers for bulk delete rather than cloning objects
This commit is contained in:
parent
361d80a720
commit
0de48d2190
|
@ -9,7 +9,12 @@ use FOS\ElasticaBundle\Persister\ObjectPersister;
|
||||||
use Symfony\Component\ExpressionLanguage\Expression;
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||||
use Symfony\Component\ExpressionLanguage\SyntaxError;
|
use Symfony\Component\ExpressionLanguage\SyntaxError;
|
||||||
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically update ElasticSearch based on changes to the Doctrine source
|
||||||
|
* data. One listener is generated for each Doctrine entity / ElasticSearch type.
|
||||||
|
*/
|
||||||
class Listener implements EventSubscriber
|
class Listener implements EventSubscriber
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -48,10 +53,14 @@ class Listener implements EventSubscriber
|
||||||
protected $isIndexableCallback;
|
protected $isIndexableCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Objects scheduled for insertion, replacement, or removal
|
* Objects scheduled for insertion and replacement
|
||||||
*/
|
*/
|
||||||
public $scheduledForInsertion = array();
|
public $scheduledForInsertion = array();
|
||||||
public $scheduledForUpdate = array();
|
public $scheduledForUpdate = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IDs of objects scheduled for removal
|
||||||
|
*/
|
||||||
public $scheduledForDeletion = array();
|
public $scheduledForDeletion = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,6 +70,13 @@ class Listener implements EventSubscriber
|
||||||
*/
|
*/
|
||||||
protected $expressionLanguage;
|
protected $expressionLanguage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PropertyAccessor instance
|
||||||
|
*
|
||||||
|
* @var PropertyAccessorInterface
|
||||||
|
*/
|
||||||
|
protected $propertyAccessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
|
@ -75,6 +91,8 @@ class Listener implements EventSubscriber
|
||||||
$this->objectClass = $objectClass;
|
$this->objectClass = $objectClass;
|
||||||
$this->events = $events;
|
$this->events = $events;
|
||||||
$this->esIdentifierField = $esIdentifierField;
|
$this->esIdentifierField = $esIdentifierField;
|
||||||
|
|
||||||
|
$this->propertyAccessor = PropertyAccess::createPropertyAccessor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,20 +213,21 @@ class Listener implements EventSubscriber
|
||||||
$this->scheduledForUpdate[] = $entity;
|
$this->scheduledForUpdate[] = $entity;
|
||||||
} else {
|
} else {
|
||||||
// Delete if no longer indexable
|
// Delete if no longer indexable
|
||||||
$this->scheduledForDeletion[] = clone $entity;
|
$this->scheduleForDeletion($entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete objects preRemove instead of postRemove so that we have access to the id
|
* Delete objects preRemove instead of postRemove so that we have access to the id. Because this is called
|
||||||
|
* preRemove, first check that the entity is managed by Doctrine
|
||||||
*/
|
*/
|
||||||
public function preRemove(EventArgs $eventArgs)
|
public function preRemove(EventArgs $eventArgs)
|
||||||
{
|
{
|
||||||
$entity = $eventArgs->getEntity();
|
$entity = $eventArgs->getEntity();
|
||||||
|
|
||||||
if ($entity instanceof $this->objectClass) {
|
if ($entity instanceof $this->objectClass) {
|
||||||
$this->scheduledForDeletion[] = clone $entity;
|
$this->scheduleForDeletion($entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +243,7 @@ class Listener implements EventSubscriber
|
||||||
$this->objectPersister->replaceMany($this->scheduledForUpdate);
|
$this->objectPersister->replaceMany($this->scheduledForUpdate);
|
||||||
}
|
}
|
||||||
if (count($this->scheduledForDeletion)) {
|
if (count($this->scheduledForDeletion)) {
|
||||||
$this->objectPersister->deleteMany($this->scheduledForDeletion);
|
$this->objectPersister->deleteManyByIdentifiers($this->scheduledForDeletion);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,4 +264,16 @@ class Listener implements EventSubscriber
|
||||||
{
|
{
|
||||||
$this->persistScheduled();
|
$this->persistScheduled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Record the specified identifier to delete. Do not need to entire object.
|
||||||
|
* @param mixed $object
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function scheduleForDeletion($object)
|
||||||
|
{
|
||||||
|
if ($identifierValue = $this->propertyAccessor->getValue($object, $this->esIdentifierField)) {
|
||||||
|
$this->scheduledForDeletion[] = $identifierValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,16 @@ class ObjectPersister implements ObjectPersisterInterface
|
||||||
$this->type->deleteDocuments($documents);
|
$this->type->deleteDocuments($documents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk deletes records from an array of identifiers
|
||||||
|
*
|
||||||
|
* @param array $identifiers array of domain model object identifiers
|
||||||
|
*/
|
||||||
|
public function deleteManyByIdentifiers(array $identifiers)
|
||||||
|
{
|
||||||
|
$this->type->getIndex()->getClient()->deleteIds($identifiers, $this->type->getIndex(), $this->type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms an object to an elastica document
|
* Transforms an object to an elastica document
|
||||||
*
|
*
|
||||||
|
|
|
@ -61,4 +61,11 @@ interface ObjectPersisterInterface
|
||||||
* @param array $objects array of domain model objects
|
* @param array $objects array of domain model objects
|
||||||
*/
|
*/
|
||||||
function deleteMany(array $objects);
|
function deleteMany(array $objects);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk deletes records from an array of identifiers
|
||||||
|
*
|
||||||
|
* @param array $identifiers array of domain model object identifiers
|
||||||
|
*/
|
||||||
|
public function deleteManyByIdentifiers(array $identifiers);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,13 +100,13 @@ abstract class ListenerTest extends \PHPUnit_Framework_TestCase
|
||||||
$listener->postUpdate($eventArgs);
|
$listener->postUpdate($eventArgs);
|
||||||
|
|
||||||
$this->assertEmpty($listener->scheduledForUpdate);
|
$this->assertEmpty($listener->scheduledForUpdate);
|
||||||
$this->assertEquals($entity, current($listener->scheduledForDeletion));
|
$this->assertEquals($entity->getId(), current($listener->scheduledForDeletion));
|
||||||
|
|
||||||
$persister->expects($this->never())
|
$persister->expects($this->never())
|
||||||
->method('replaceOne');
|
->method('replaceOne');
|
||||||
$persister->expects($this->once())
|
$persister->expects($this->once())
|
||||||
->method('deleteMany')
|
->method('deleteManyByIdentifiers')
|
||||||
->with(array($entity));
|
->with(array($entity->getId()));
|
||||||
|
|
||||||
$listener->postFlush($eventArgs);
|
$listener->postFlush($eventArgs);
|
||||||
}
|
}
|
||||||
|
@ -133,13 +133,11 @@ abstract class ListenerTest extends \PHPUnit_Framework_TestCase
|
||||||
$listener = $this->createListener($persister, get_class($entity), array());
|
$listener = $this->createListener($persister, get_class($entity), array());
|
||||||
$listener->preRemove($eventArgs);
|
$listener->preRemove($eventArgs);
|
||||||
|
|
||||||
$scheduledClone = current($listener->scheduledForDeletion);
|
$this->assertEquals($entity->getId(), current($listener->scheduledForDeletion));
|
||||||
$this->assertEquals($entity, $scheduledClone);
|
|
||||||
$this->assertNotSame($entity, $scheduledClone);
|
|
||||||
|
|
||||||
$persister->expects($this->once())
|
$persister->expects($this->once())
|
||||||
->method('deleteMany')
|
->method('deleteManyByIdentifiers')
|
||||||
->with(array($entity));
|
->with(array($entity->getId()));
|
||||||
|
|
||||||
$listener->postFlush($eventArgs);
|
$listener->postFlush($eventArgs);
|
||||||
}
|
}
|
||||||
|
@ -151,6 +149,7 @@ abstract class ListenerTest extends \PHPUnit_Framework_TestCase
|
||||||
$persister = $this->getMockPersister();
|
$persister = $this->getMockPersister();
|
||||||
|
|
||||||
$entity = new Listener\Entity(1);
|
$entity = new Listener\Entity(1);
|
||||||
|
$entity->identifier = 'foo';
|
||||||
$eventArgs = $this->createLifecycleEventArgs($entity, $objectManager);
|
$eventArgs = $this->createLifecycleEventArgs($entity, $objectManager);
|
||||||
|
|
||||||
$objectManager->expects($this->any())
|
$objectManager->expects($this->any())
|
||||||
|
@ -166,13 +165,11 @@ abstract class ListenerTest extends \PHPUnit_Framework_TestCase
|
||||||
$listener = $this->createListener($persister, get_class($entity), array(), 'identifier');
|
$listener = $this->createListener($persister, get_class($entity), array(), 'identifier');
|
||||||
$listener->preRemove($eventArgs);
|
$listener->preRemove($eventArgs);
|
||||||
|
|
||||||
$scheduledClone = current($listener->scheduledForDeletion);
|
$this->assertEquals($entity->identifier, current($listener->scheduledForDeletion));
|
||||||
$this->assertEquals($entity, $scheduledClone);
|
|
||||||
$this->assertNotSame($entity, $scheduledClone);
|
|
||||||
|
|
||||||
$persister->expects($this->once())
|
$persister->expects($this->once())
|
||||||
->method('deleteMany')
|
->method('deleteManyByIdentifiers')
|
||||||
->with(array($entity));
|
->with(array($entity->identifier));
|
||||||
|
|
||||||
$listener->postFlush($eventArgs);
|
$listener->postFlush($eventArgs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue