Commit 3b6b96ea authored by Jeremy Mikola's avatar Jeremy Mikola

PHPLIB-112: Support typeMap option for non-cursor aggregate operations

parent c73dbf29
......@@ -49,11 +49,6 @@ source:
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: typeMap
post: |
.. note::
This is not supported for inline aggregation results (i.e. ``useCursor``
option is ``false`` or the server version is < 2.6).
---
arg_name: option
name: useCursor
......
......@@ -58,14 +58,6 @@ MongoDB server version and whether the ``useCursor`` option is specified. If
``result`` array from the command response document. In both cases, the return
value will be :php:`Traversable <traversable>`.
.. note::
BSON deserialization of inline aggregation results (i.e. not using a command
cursor) does not yet support a ``typeMap`` option. Classes implementing
:php:`MongoDB\\BSON\\Persistable <mongodb-bson-persistable>` will still be
deserialized according to the
:php:`Persistence <mongodb.persistence.deserialization>` specification.
.. todo: add examples
See Also
......
......@@ -153,10 +153,6 @@ class Collection
* returned; otherwise, an ArrayIterator is returned, which wraps the
* "result" array from the command response document.
*
* Note: BSON deserialization of inline aggregation results (i.e. not using
* a command cursor) does not yet support a custom type map
* (depends on: https://jira.mongodb.org/browse/PHPC-314).
*
* @see Aggregate::__construct() for supported options
* @param array $pipeline List of pipeline operations
* @param array $options Command options
......
<?php
namespace MongoDB\Model;
use ArrayIterator;
/**
* Iterator for applying a type map to documents in inline command results.
*
* This iterator may be used to apply a type map to an array of documents
* returned by a database command (e.g. aggregate on servers < 2.6) and allows
* for functional equivalence with commands that return their results via a
* cursor (e.g. aggregate on servers >= 2.6).
*
* @internal
*/
class TypeMapArrayIterator extends ArrayIterator
{
private $typeMap;
/**
* Constructor.
*
* @param array $documents
* @param array $typeMap
*/
public function __construct(array $documents = [], array $typeMap)
{
parent::__construct($documents);
$this->typeMap = $typeMap;
}
/**
* Return the current element with the type map applied to it.
*
* @see http://php.net/arrayiterator.current
* @return array|object
*/
public function current()
{
return \MongoDB\apply_type_map_to_document(parent::current(), $this->typeMap);
}
}
......@@ -11,6 +11,7 @@ use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\Model\TypeMapArrayIterator;
use ArrayIterator;
use stdClass;
use Traversable;
......@@ -72,9 +73,6 @@ class Aggregate implements Executable
* * typeMap (array): Type map for BSON deserialization. This will be
* applied to the returned Cursor (it is not sent to the server).
*
* This is not supported for inline aggregation results (i.e. useCursor
* option is false or the server version is < 2.6).
*
* * useCursor (boolean): Indicates whether the command will request that
* the server provide results using a cursor. The default is true.
*
......@@ -206,9 +204,6 @@ class Aggregate implements Executable
$cursor = $server->executeCommand($this->databaseName, $command, $readPreference);
if ($isCursorSupported && $this->options['useCursor']) {
/* The type map can only be applied to command cursors until
* https://jira.mongodb.org/browse/PHPC-314 is implemented.
*/
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
}
......@@ -222,6 +217,10 @@ class Aggregate implements Executable
throw new UnexpectedValueException('aggregate command did not return a "result" array');
}
if (isset($this->options['typeMap'])) {
return new TypeMapArrayIterator($result->result, $this->options['typeMap']);
}
return new ArrayIterator($result->result);
}
......
......@@ -21,24 +21,27 @@ class AggregateFunctionalTest extends FunctionalTestCase
/**
* @dataProvider provideTypeMapOptionsAndExpectedDocument
*/
public function testTypeMapOption(array $typeMap, array $expectedDocuments)
public function testTypeMapOption(array $typeMap = null, array $expectedDocuments)
{
if ( ! \MongoDB\server_supports_feature($this->getPrimaryServer(), self::$wireVersionForCursor)) {
$this->markTestSkipped('Command cursor is not supported');
}
$this->createFixtures(3);
$pipeline = [['$match' => ['_id' => ['$ne' => 2]]]];
$operation = new Aggregate($this->getDatabaseName(), $this->getCollectionName(), $pipeline, ['typeMap' => $typeMap]);
$cursor = $operation->execute($this->getPrimaryServer());
$results = iterator_to_array($operation->execute($this->getPrimaryServer()));
$this->assertEquals($expectedDocuments, $cursor->toArray());
$this->assertEquals($expectedDocuments, $results);
}
public function provideTypeMapOptionsAndExpectedDocument()
{
return [
[
null,
[
(object) ['_id' => 1, 'x' => (object) ['foo' => 'bar']],
(object) ['_id' => 3, 'x' => (object) ['foo' => 'bar']],
],
],
[
['root' => 'array', 'document' => 'array'],
[
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment