diff --git a/CHANGELOG-3.0.md b/CHANGELOG-3.0.md new file mode 100644 index 0000000..534a25e --- /dev/null +++ b/CHANGELOG-3.0.md @@ -0,0 +1,17 @@ +CHANGELOG for 3.0.x +=================== + +This changelog references the relevant changes (bug and security fixes) done +in 3.0 minor versions. + +To get the diff for a specific change, go to +https://github.com/FriendsOfSymfony/FOSElasticaBundle/commit/XXX where XXX is +the commit hash. To get the diff between two versions, go to +https://github.com/FriendsOfSymfony/FOSElasticaBundle/compare/v3.0.0...v3.0.1 + +To generate a changelog summary since the last version, run +`git log --no-merges --oneline v3.0.0...3.0.x` + +* 3.0.0-ALPHA2 (2014-xx-xx) + + * 41bf07e: Renamed the `no-stop-on-error` option in PopulateCommand to `ignore-errors` diff --git a/Client.php b/Client.php index 67252ec..679317c 100644 --- a/Client.php +++ b/Client.php @@ -27,7 +27,7 @@ class Client extends ElasticaClient 'transport' => $connection->getTransport(), ); - $this->_logger->logQuery($path, $method, $data, $time, $connection_array); + $this->_logger->logQuery($path, $method, $data, $time, $connection_array, $query); } return $response; diff --git a/Command/PopulateCommand.php b/Command/PopulateCommand.php old mode 100755 new mode 100644 index 31ecc4b..98834c7 --- a/Command/PopulateCommand.php +++ b/Command/PopulateCommand.php @@ -45,6 +45,7 @@ class PopulateCommand extends ContainerAwareCommand ->addOption('offset', null, InputOption::VALUE_REQUIRED, 'Start indexing at offset', 0) ->addOption('sleep', null, InputOption::VALUE_REQUIRED, 'Sleep time between persisting iterations (microseconds)', 0) ->addOption('batch-size', null, InputOption::VALUE_REQUIRED, 'Index packet size (overrides provider config option)') + ->addOption('ignore-errors', null, InputOption::VALUE_NONE, 'Do not stop on errors') ->setDescription('Populates search indexes from providers') ; } @@ -66,11 +67,12 @@ class PopulateCommand extends ContainerAwareCommand { $index = $input->getOption('index'); $type = $input->getOption('type'); - $reset = $input->getOption('no-reset') ? false : true; - $noInteraction = $input->getOption('no-interaction'); + $reset = !$input->getOption('no-reset'); $options = $input->getOptions(); - if (!$noInteraction && $reset && $input->getOption('offset')) { + $options['ignore-errors'] = $input->hasOption('ignore-errors'); + + if ($input->isInteractive() && $reset && $input->getOption('offset')) { /** @var DialogHelper $dialog */ $dialog = $this->getHelperSet()->get('dialog'); if (!$dialog->askConfirmation($output, 'You chose to reset the index and start indexing with an offset. Do you really want to do that?', true)) { @@ -107,7 +109,7 @@ class PopulateCommand extends ContainerAwareCommand */ private function populateIndex(OutputInterface $output, $index, $reset, $options) { - if ($reset) { + if ($reset && $this->indexManager->getIndex($index)->exists()) { $output->writeln(sprintf('Resetting %s', $index)); $this->resetter->resetIndex($index); } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 403de85..b5d2ecc 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -101,7 +101,12 @@ class Configuration implements ConfigurationInterface ->arrayNode('servers') ->prototype('array') ->children() - ->scalarNode('url')->end() + ->scalarNode('url') + ->validate() + ->ifTrue(function($url) { return substr($url, -1) !== '/'; }) + ->then(function($url) { return $url.'/'; }) + ->end() + ->end() ->scalarNode('host')->end() ->scalarNode('port')->end() ->scalarNode('logger') @@ -109,6 +114,7 @@ class Configuration implements ConfigurationInterface ->treatNullLike('fos_elastica.logger') ->treatTrueLike('fos_elastica.logger') ->end() + ->scalarNode('timeout')->end() ->end() ->end() ->end() @@ -410,6 +416,10 @@ class Configuration implements ConfigurationInterface } if (isset($nestings['properties'])) { + $node + ->booleanNode('include_in_parent')->end() + ->booleanNode('include_in_root')->end() + ; $this->addNestedFieldConfig($node, $nestings, 'properties'); } } diff --git a/DependencyInjection/FOSElasticaExtension.php b/DependencyInjection/FOSElasticaExtension.php index a67be0f..52b6bd5 100644 --- a/DependencyInjection/FOSElasticaExtension.php +++ b/DependencyInjection/FOSElasticaExtension.php @@ -4,6 +4,7 @@ namespace FOS\ElasticaBundle\DependencyInjection; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; @@ -203,6 +204,10 @@ class FOSElasticaExtension extends Extension if (isset($type['serializer']['version'])) { $callbackDef->addMethodCall('setVersion', array($type['serializer']['version'])); } + $callbackClassImplementedInterfaces = class_implements($this->serializerConfig['callback_class']); // PHP < 5.4 friendly + if (isset($callbackClassImplementedInterfaces['Symfony\Component\DependencyInjection\ContainerAwareInterface'])) { + $callbackDef->addMethodCall('setContainer', array(new Reference('service_container'))); + } $container->setDefinition($callbackId, $callbackDef); diff --git a/Doctrine/AbstractProvider.php b/Doctrine/AbstractProvider.php index 1fb41f5..9d1575c 100644 --- a/Doctrine/AbstractProvider.php +++ b/Doctrine/AbstractProvider.php @@ -3,6 +3,7 @@ namespace FOS\ElasticaBundle\Doctrine; use Doctrine\Common\Persistence\ManagerRegistry; +use Elastica\Exception\Bulk\ResponseException as BulkResponseException; use FOS\ElasticaBundle\Persister\ObjectPersisterInterface; use FOS\ElasticaBundle\Provider\AbstractProvider as BaseAbstractProvider; @@ -22,6 +23,7 @@ abstract class AbstractProvider extends BaseAbstractProvider { parent::__construct($objectPersister, $objectClass, array_merge(array( 'clear_object_manager' => true, + 'ignore_errors' => false, 'query_builder_method' => 'createQueryBuilder', ), $options)); @@ -38,6 +40,7 @@ abstract class AbstractProvider extends BaseAbstractProvider $offset = isset($options['offset']) ? intval($options['offset']) : 0; $sleep = isset($options['sleep']) ? intval($options['sleep']) : 0; $batchSize = isset($options['batch-size']) ? intval($options['batch-size']) : $this->options['batch_size']; + $ignoreErrors = isset($options['ignore-errors']) ? $options['ignore-errors'] : $this->options['ignore_errors']; for (; $offset < $nbObjects; $offset += $batchSize) { if ($loggerClosure) { @@ -45,7 +48,17 @@ abstract class AbstractProvider extends BaseAbstractProvider } $objects = $this->fetchSlice($queryBuilder, $batchSize, $offset); - $this->objectPersister->insertMany($objects); + if (!$ignoreErrors) { + $this->objectPersister->insertMany($objects); + } else { + try { + $this->objectPersister->insertMany($objects); + } catch(BulkResponseException $e) { + if ($loggerClosure) { + $loggerClosure(sprintf('%s',$e->getMessage())); + } + } + } if ($this->options['clear_object_manager']) { $this->managerRegistry->getManagerForClass($this->objectClass)->clear(); @@ -58,7 +71,7 @@ abstract class AbstractProvider extends BaseAbstractProvider $stepCount = $stepNbObjects + $offset; $percentComplete = 100 * $stepCount / $nbObjects; $objectsPerSecond = $stepNbObjects / (microtime(true) - $stepStartTime); - $loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s', $percentComplete, $stepCount, $nbObjects, $objectsPerSecond)); + $loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s %s', $percentComplete, $stepCount, $nbObjects, $objectsPerSecond, $this->getMemoryUsage())); } } } diff --git a/Finder/FinderInterface.php b/Finder/FinderInterface.php index 4805d58..7c257de 100644 --- a/Finder/FinderInterface.php +++ b/Finder/FinderInterface.php @@ -9,7 +9,8 @@ interface FinderInterface * * @param mixed $query Can be a string, an array or an \Elastica\Query object * @param int $limit How many results to get + * @param array $options * @return array results */ - function find($query, $limit = null); + function find($query, $limit = null, $options = array()); } diff --git a/Finder/PaginatedFinderInterface.php b/Finder/PaginatedFinderInterface.php index 3581cda..fa10b70 100644 --- a/Finder/PaginatedFinderInterface.php +++ b/Finder/PaginatedFinderInterface.php @@ -12,15 +12,17 @@ interface PaginatedFinderInterface extends FinderInterface * Searches for query results and returns them wrapped in a paginator * * @param mixed $query Can be a string, an array or an \Elastica\Query object + * @param array $options * @return Pagerfanta paginated results */ - function findPaginated($query); + function findPaginated($query, $options = array()); /** * Creates a paginator adapter for this query * * @param mixed $query + * @param array $options * @return PaginatorAdapterInterface */ - function createPaginatorAdapter($query); + function createPaginatorAdapter($query, $options = array()); } diff --git a/Finder/TransformedFinder.php b/Finder/TransformedFinder.php index 4c8aa98..9080701 100644 --- a/Finder/TransformedFinder.php +++ b/Finder/TransformedFinder.php @@ -29,18 +29,19 @@ class TransformedFinder implements PaginatedFinderInterface * * @param string $query * @param integer $limit + * @param array $options * @return array of model objects **/ - public function find($query, $limit = null) + public function find($query, $limit = null, $options = array()) { - $results = $this->search($query, $limit); + $results = $this->search($query, $limit, $options); return $this->transformer->transform($results); } - public function findHybrid($query, $limit = null) + public function findHybrid($query, $limit = null, $options = array()) { - $results = $this->search($query, $limit); + $results = $this->search($query, $limit, $options); return $this->transformer->hybridTransform($results); } @@ -64,15 +65,16 @@ class TransformedFinder implements PaginatedFinderInterface /** * @param $query * @param null|int $limit + * @param array $options * @return array */ - protected function search($query, $limit = null) + protected function search($query, $limit = null, $options = array()) { $queryObject = Query::create($query); if (null !== $limit) { $queryObject->setSize($limit); } - $results = $this->searchable->search($queryObject)->getResults(); + $results = $this->searchable->search($queryObject, $options)->getResults(); return $results; } @@ -81,12 +83,13 @@ class TransformedFinder implements PaginatedFinderInterface * Gets a paginator wrapping the result of a search * * @param string $query + * @param array $options * @return Pagerfanta */ - public function findPaginated($query) + public function findPaginated($query, $options = array()) { $queryObject = Query::create($query); - $paginatorAdapter = $this->createPaginatorAdapter($queryObject); + $paginatorAdapter = $this->createPaginatorAdapter($queryObject, $options); return new Pagerfanta(new FantaPaginatorAdapter($paginatorAdapter)); } @@ -94,10 +97,10 @@ class TransformedFinder implements PaginatedFinderInterface /** * {@inheritdoc} */ - public function createPaginatorAdapter($query) + public function createPaginatorAdapter($query, $options = array()) { $query = Query::create($query); - return new TransformedPaginatorAdapter($this->searchable, $query, $this->transformer); + return new TransformedPaginatorAdapter($this->searchable, $query, $options, $this->transformer); } } diff --git a/Logger/ElasticaLogger.php b/Logger/ElasticaLogger.php index 7aacac5..5b1269f 100644 --- a/Logger/ElasticaLogger.php +++ b/Logger/ElasticaLogger.php @@ -14,33 +14,44 @@ use Psr\Log\LoggerInterface; */ class ElasticaLogger implements LoggerInterface { + /** + * @var LoggerInterface + */ protected $logger; - protected $queries; + + /** + * @var array + */ + protected $queries = array(); + + /** + * @var boolean + */ protected $debug; /** * Constructor. * * @param LoggerInterface|null $logger The Symfony logger - * @param bool $debug + * @param boolean $debug */ public function __construct(LoggerInterface $logger = null, $debug = false) { $this->logger = $logger; - $this->queries = array(); $this->debug = $debug; } /** * Logs a query. * - * @param string $path Path to call - * @param string $method Rest method to use (GET, POST, DELETE, PUT) - * @param array $data arguments - * @param float $time execution time - * @param array $connection host, port and transport of the query + * @param string $path Path to call + * @param string $method Rest method to use (GET, POST, DELETE, PUT) + * @param array $data Arguments + * @param float $time Execution time + * @param array $connection Host, port and transport of the query + * @param array $query Arguments */ - public function logQuery($path, $method, $data, $time, $connection = array()) + public function logQuery($path, $method, $data, $time, $connection = array(), $query = array()) { if ($this->debug) { $this->queries[] = array( @@ -48,7 +59,8 @@ class ElasticaLogger implements LoggerInterface 'method' => $method, 'data' => $data, 'executionMS' => $time, - 'connection' => $connection + 'connection' => $connection, + 'queryString' => $query, ); } diff --git a/Paginator/RawPaginatorAdapter.php b/Paginator/RawPaginatorAdapter.php index d4b5357..b74a9e4 100644 --- a/Paginator/RawPaginatorAdapter.php +++ b/Paginator/RawPaginatorAdapter.php @@ -22,13 +22,18 @@ class RawPaginatorAdapter implements PaginatorAdapterInterface */ private $query; + /** + * @var array search options + */ + private $options; + /** * @var integer the number of hits */ private $totalHits; /** - * @array for the facets + * @var array for the facets */ private $facets; @@ -38,10 +43,11 @@ class RawPaginatorAdapter implements PaginatorAdapterInterface * @param SearchableInterface $searchable the object to search in * @param Query $query the query to search */ - public function __construct(SearchableInterface $searchable, Query $query) + public function __construct(SearchableInterface $searchable, Query $query, array $options = array()) { $this->searchable = $searchable; $this->query = $query; + $this->options = $options; } /** @@ -72,7 +78,7 @@ class RawPaginatorAdapter implements PaginatorAdapterInterface $query->setFrom($offset); $query->setSize($itemCountPerPage); - $resultSet = $this->searchable->search($query); + $resultSet = $this->searchable->search($query, $this->options); $this->totalHits = $resultSet->getTotalHits(); $this->facets = $resultSet->getFacets(); return $resultSet; diff --git a/Paginator/TransformedPaginatorAdapter.php b/Paginator/TransformedPaginatorAdapter.php index 7bc038a..10976f7 100644 --- a/Paginator/TransformedPaginatorAdapter.php +++ b/Paginator/TransformedPaginatorAdapter.php @@ -18,9 +18,9 @@ class TransformedPaginatorAdapter extends RawPaginatorAdapter * @param Query $query the query to search * @param ElasticaToModelTransformerInterface $transformer the transformer for fetching the results */ - public function __construct(SearchableInterface $searchable, Query $query, ElasticaToModelTransformerInterface $transformer) + public function __construct(SearchableInterface $searchable, Query $query, array $options = array(), ElasticaToModelTransformerInterface $transformer) { - parent::__construct($searchable, $query); + parent::__construct($searchable, $query, $options); $this->transformer = $transformer; } diff --git a/Propel/Provider.php b/Propel/Provider.php index c319691..393beba 100644 --- a/Propel/Provider.php +++ b/Propel/Provider.php @@ -41,7 +41,7 @@ class Provider extends AbstractProvider $stepCount = $stepNbObjects + $offset; $percentComplete = 100 * $stepCount / $nbObjects; $objectsPerSecond = $stepNbObjects / (microtime(true) - $stepStartTime); - $loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s', $percentComplete, $stepCount, $nbObjects, $objectsPerSecond)); + $loggerClosure(sprintf('%0.1f%% (%d/%d), %d objects/s %s', $percentComplete, $stepCount, $nbObjects, $objectsPerSecond, $this->getMemoryUsage())); } } } diff --git a/Provider/AbstractProvider.php b/Provider/AbstractProvider.php index 06883a3..2761a25 100644 --- a/Provider/AbstractProvider.php +++ b/Provider/AbstractProvider.php @@ -4,10 +4,24 @@ namespace FOS\ElasticaBundle\Provider; use FOS\ElasticaBundle\Persister\ObjectPersisterInterface; +/** + * AbstractProvider + */ abstract class AbstractProvider implements ProviderInterface { - protected $objectClass; + /** + * @var ObjectPersisterInterface + */ protected $objectPersister; + + /** + * @var string + */ + protected $objectClass; + + /** + * @var array + */ protected $options; /** @@ -26,4 +40,17 @@ abstract class AbstractProvider implements ProviderInterface 'batch_size' => 100, ), $options); } + + /** + * Get string with RAM usage information (current and peak) + * + * @return string + */ + protected function getMemoryUsage() + { + $memory = round(memory_get_usage() / (1024 * 1024)); // to get usage in Mo + $memoryMax = round(memory_get_peak_usage() / (1024 * 1024)); // to get max usage in Mo + + return sprintf('(RAM : current=%uMo peak=%uMo)', $memory, $memoryMax); + } } diff --git a/README.md b/README.md index f78c97f..aaaf0a5 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Most of the time, you will need only one. clients: default: { host: localhost, port: 9200 } +A client configuration can also override the Elastica logger to change the used class ```logger: ``` or to simply disable it ```logger: false```. Disabling the logger should be done on production because it can cause a memory leak. #### Declare a serializer diff --git a/Repository.php b/Repository.php index 413f1e4..70b2a21 100644 --- a/Repository.php +++ b/Repository.php @@ -19,23 +19,23 @@ class Repository $this->finder = $finder; } - public function find($query, $limit=null) + public function find($query, $limit = null, $options = array()) { - return $this->finder->find($query, $limit); + return $this->finder->find($query, $limit, $options); } - public function findHybrid($query, $limit=null) + public function findHybrid($query, $limit = null, $options = array()) { - return $this->finder->findHybrid($query, $limit); + return $this->finder->findHybrid($query, $limit, $options); } - public function findPaginated($query) + public function findPaginated($query, $options = array()) { - return $this->finder->findPaginated($query); + return $this->finder->findPaginated($query, $options); } - public function createPaginatorAdapter($query) + public function createPaginatorAdapter($query, $options = array()) { - return $this->finder->createPaginatorAdapter($query); + return $this->finder->createPaginatorAdapter($query, $options); } } diff --git a/Resetter.php b/Resetter.php index 4a7f13b..c7f4638 100644 --- a/Resetter.php +++ b/Resetter.php @@ -4,6 +4,7 @@ namespace FOS\ElasticaBundle; use Elastica\Exception\ExceptionInterface; use Elastica\Index; +use Elastica\Exception\ResponseException; use Elastica\Type\Mapping; /** @@ -71,7 +72,13 @@ class Resetter } $type = $indexConfig['index']->getType($typeName); - $type->delete(); + try { + $type->delete(); + } catch (ResponseException $e) { + if (strpos($e->getMessage(), 'TypeMissingException') === false) { + throw $e; + } + } $mapping = $this->createMapping($indexConfig['config']['mappings'][$typeName]); $type->setMapping($mapping); } @@ -86,12 +93,15 @@ class Resetter { $mapping = Mapping::create($indexConfig['properties']); - if (isset($indexConfig['_parent'])) { - $mapping->setParam('_parent', array('type' => $indexConfig['_parent']['type'])); + $mappingSpecialFields = array('_uid', '_id', '_source', '_all', '_analyzer', '_boost', '_routing', '_index', '_size', '_timestamp', '_ttl', 'dynamic_templates'); + foreach ($mappingSpecialFields as $specialField) { + if (isset($indexConfig[$specialField])) { + $mapping->setParam($specialField, $indexConfig[$specialField]); + } } - if (isset($indexConfig['dynamic_templates'])) { - $mapping->setParam('dynamic_templates', $indexConfig['dynamic_templates']); + if (isset($indexConfig['_parent'])) { + $mapping->setParam('_parent', array('type' => $indexConfig['_parent']['type'])); } return $mapping; diff --git a/Resources/views/Collector/elastica.html.twig b/Resources/views/Collector/elastica.html.twig index 0eb50a6..637dae7 100644 --- a/Resources/views/Collector/elastica.html.twig +++ b/Resources/views/Collector/elastica.html.twig @@ -44,6 +44,7 @@ {% for key, query in collector.queries %}
  • Path: {{ query.path }}
    + Query: {{ query.queryString|url_encode }}
    Method: {{ query.method }} ({{ query.connection.transport }} on {{ query.connection.host }}:{{ query.connection.port }})
    {{ query.data|json_encode }} @@ -60,7 +61,7 @@ {% endif %}
  • diff --git a/Tests/ClientTest.php b/Tests/ClientTest.php index c8509cf..8a9d91a 100644 --- a/Tests/ClientTest.php +++ b/Tests/ClientTest.php @@ -24,6 +24,7 @@ class ClientTest extends \PHPUnit_Framework_TestCase Request::GET, $this->isType('array'), $this->isType('float'), + $this->isType('array'), $this->isType('array') ); diff --git a/Tests/DependencyInjection/ConfigurationTest.php b/Tests/DependencyInjection/ConfigurationTest.php index 35b2af3..0f0d374 100644 --- a/Tests/DependencyInjection/ConfigurationTest.php +++ b/Tests/DependencyInjection/ConfigurationTest.php @@ -3,6 +3,7 @@ namespace FOS\ElasticaBundle\Tests\Resetter\DependencyInjection; use FOS\ElasticaBundle\DependencyInjection\Configuration; +use Symfony\Component\Config\Definition\Processor; /** * ConfigurationTest @@ -85,4 +86,21 @@ class ConfigurationTest extends \PHPUnit_Framework_TestCase $this->assertInstanceOf('Symfony\Component\Config\Definition\ScalarNode', $mapping['index']); $this->assertNull($mapping['index']->getDefaultValue()); } + + public function testSlashIsAddedAtTheEndOfServerUrl() + { + $config = array( + 'clients' => array( + 'default' => array( + 'url' => 'http://www.github.com', + ), + ), + ); + + $processor = new Processor(); + + $configuration = $processor->processConfiguration($this->configuration, array($config)); + + $this->assertEquals('http://www.github.com/', $configuration['clients']['default']['servers'][0]['url']); + } } diff --git a/Tests/Doctrine/AbstractProviderTest.php b/Tests/Doctrine/AbstractProviderTest.php index 0a9aceb..2492eed 100644 --- a/Tests/Doctrine/AbstractProviderTest.php +++ b/Tests/Doctrine/AbstractProviderTest.php @@ -135,6 +135,30 @@ class AbstractProviderTest extends \PHPUnit_Framework_TestCase $this->assertTrue($loggerClosureInvoked); } + public function testPopulateNotStopOnError() + { + $nbObjects = 1; + $objects = array(1); + + $provider = $this->getMockAbstractProvider(); + + $provider->expects($this->any()) + ->method('countObjects') + ->will($this->returnValue($nbObjects)); + + $provider->expects($this->any()) + ->method('fetchSlice') + ->will($this->returnValue($objects)); + + $this->objectPersister->expects($this->any()) + ->method('insertMany') + ->will($this->throwException($this->getMockBulkResponseException())); + + $this->setExpectedException('Elastica\Exception\Bulk\ResponseException'); + + $provider->populate(null, array('ignore-errors' => false)); + } + /** * @return \FOS\ElasticaBundle\Doctrine\AbstractProvider|\PHPUnit_Framework_MockObject_MockObject */ @@ -148,6 +172,16 @@ class AbstractProviderTest extends \PHPUnit_Framework_TestCase )); } + /** + * @return \Elastica\Exception\Bulk\ResponseException + */ + private function getMockBulkResponseException() + { + return $this->getMockBuilder('Elastica\Exception\Bulk\ResponseException') + ->disableOriginalConstructor() + ->getMock(); + } + /** * @return \Doctrine\Common\Persistence\ManagerRegistry|\PHPUnit_Framework_MockObject_MockObject */ diff --git a/Tests/Logger/ElasticaLoggerTest.php b/Tests/Logger/ElasticaLoggerTest.php index 30ce30c..96adf53 100644 --- a/Tests/Logger/ElasticaLoggerTest.php +++ b/Tests/Logger/ElasticaLoggerTest.php @@ -70,6 +70,7 @@ class ElasticaLoggerTest extends \PHPUnit_Framework_TestCase $data = array('data'); $time = 12; $connection = array('host' => 'localhost', 'port' => '8999', 'transport' => 'https'); + $query = array('search_type' => 'dfs_query_then_fetch'); $expected = array( 'path' => $path, @@ -77,9 +78,10 @@ class ElasticaLoggerTest extends \PHPUnit_Framework_TestCase 'data' => $data, 'executionMS' => $time, 'connection' => $connection, + 'queryString' => $query, ); - $elasticaLogger->logQuery($path, $method, $data, $time, $connection); + $elasticaLogger->logQuery($path, $method, $data, $time, $connection, $query); $returnedQueries = $elasticaLogger->getQueries(); $this->assertEquals($expected, $returnedQueries[0]); } diff --git a/Tests/ResetterTest.php b/Tests/ResetterTest.php index aa0fbcc..b4e5649 100644 --- a/Tests/ResetterTest.php +++ b/Tests/ResetterTest.php @@ -2,6 +2,9 @@ namespace FOS\ElasticaBundle\Tests\Resetter; +use Elastica\Exception\ResponseException; +use Elastica\Request; +use Elastica\Response; use FOS\ElasticaBundle\Resetter; use Elastica\Type\Mapping; @@ -130,6 +133,32 @@ class ResetterTest extends \PHPUnit_Framework_TestCase $resetter->resetIndexType('foo', 'c'); } + public function testResetIndexTypeIgnoreTypeMissingException() + { + $type = $this->getMockElasticaType(); + + $this->indexConfigsByName['foo']['index']->expects($this->once()) + ->method('getType') + ->with('a') + ->will($this->returnValue($type)); + + $type->expects($this->once()) + ->method('delete') + ->will($this->throwException(new ResponseException( + new Request(''), + new Response(array('error' => 'TypeMissingException[[de_20131022] type[bla] missing]', 'status' => 404))) + )); + + $mapping = Mapping::create($this->indexConfigsByName['foo']['config']['mappings']['a']['properties']); + $mapping->setParam('dynamic_templates', $this->indexConfigsByName['foo']['config']['mappings']['a']['dynamic_templates']); + $type->expects($this->once()) + ->method('setMapping') + ->with($mapping); + + $resetter = new Resetter($this->indexConfigsByName); + $resetter->resetIndexType('foo', 'a'); + } + public function testIndexMappingForParent() { $type = $this->getMockElasticaType(); diff --git a/Transformer/ElasticaToModelTransformerCollection.php b/Transformer/ElasticaToModelTransformerCollection.php index a261e81..f65f8db 100644 --- a/Transformer/ElasticaToModelTransformerCollection.php +++ b/Transformer/ElasticaToModelTransformerCollection.php @@ -67,7 +67,9 @@ class ElasticaToModelTransformerCollection implements ElasticaToModelTransformer $result = array(); foreach ($elasticaObjects as $object) { - $result[] = $transformed[$object->getType()][$object->getId()]; + if (array_key_exists($object->getId(), $transformed[$object->getType()])) { + $result[] = $transformed[$object->getType()][$object->getId()]; + } } return $result; diff --git a/composer.json b/composer.json index 094eba5..e588494 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "symfony/console": "~2.1", "symfony/form": "~2.1", "symfony/property-access": "~2.2", - "ruflin/elastica": "~0.20", + "ruflin/elastica": ">=0.20, <1.1-dev", "psr/log": "~1.0" }, "require-dev":{