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: ...@@ -49,11 +49,6 @@ source:
source: source:
file: apiargs-MongoDBCollection-common-option.yaml file: apiargs-MongoDBCollection-common-option.yaml
ref: typeMap 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 arg_name: option
name: useCursor name: useCursor
......
...@@ -58,14 +58,6 @@ MongoDB server version and whether the ``useCursor`` option is specified. If ...@@ -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 ``result`` array from the command response document. In both cases, the return
value will be :php:`Traversable <traversable>`. 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 .. todo: add examples
See Also See Also
......
...@@ -153,10 +153,6 @@ class Collection ...@@ -153,10 +153,6 @@ class Collection
* returned; otherwise, an ArrayIterator is returned, which wraps the * returned; otherwise, an ArrayIterator is returned, which wraps the
* "result" array from the command response document. * "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 * @see Aggregate::__construct() for supported options
* @param array $pipeline List of pipeline operations * @param array $pipeline List of pipeline operations
* @param array $options Command options * @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; ...@@ -11,6 +11,7 @@ use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException; use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException; use MongoDB\Exception\UnsupportedException;
use MongoDB\Model\TypeMapArrayIterator;
use ArrayIterator; use ArrayIterator;
use stdClass; use stdClass;
use Traversable; use Traversable;
...@@ -72,9 +73,6 @@ class Aggregate implements Executable ...@@ -72,9 +73,6 @@ class Aggregate implements Executable
* * typeMap (array): Type map for BSON deserialization. This will be * * typeMap (array): Type map for BSON deserialization. This will be
* applied to the returned Cursor (it is not sent to the server). * 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 * * useCursor (boolean): Indicates whether the command will request that
* the server provide results using a cursor. The default is true. * the server provide results using a cursor. The default is true.
* *
...@@ -206,9 +204,6 @@ class Aggregate implements Executable ...@@ -206,9 +204,6 @@ class Aggregate implements Executable
$cursor = $server->executeCommand($this->databaseName, $command, $readPreference); $cursor = $server->executeCommand($this->databaseName, $command, $readPreference);
if ($isCursorSupported && $this->options['useCursor']) { 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'])) { if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']); $cursor->setTypeMap($this->options['typeMap']);
} }
...@@ -222,6 +217,10 @@ class Aggregate implements Executable ...@@ -222,6 +217,10 @@ class Aggregate implements Executable
throw new UnexpectedValueException('aggregate command did not return a "result" array'); 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); return new ArrayIterator($result->result);
} }
......
...@@ -21,24 +21,27 @@ class AggregateFunctionalTest extends FunctionalTestCase ...@@ -21,24 +21,27 @@ class AggregateFunctionalTest extends FunctionalTestCase
/** /**
* @dataProvider provideTypeMapOptionsAndExpectedDocument * @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); $this->createFixtures(3);
$pipeline = [['$match' => ['_id' => ['$ne' => 2]]]]; $pipeline = [['$match' => ['_id' => ['$ne' => 2]]]];
$operation = new Aggregate($this->getDatabaseName(), $this->getCollectionName(), $pipeline, ['typeMap' => $typeMap]); $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() public function provideTypeMapOptionsAndExpectedDocument()
{ {
return [ return [
[
null,
[
(object) ['_id' => 1, 'x' => (object) ['foo' => 'bar']],
(object) ['_id' => 3, 'x' => (object) ['foo' => 'bar']],
],
],
[ [
['root' => 'array', 'document' => 'array'], ['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