PHPLIB-242: Add typeMap support for distinct

parent 3c9064a8
...@@ -19,4 +19,10 @@ source: ...@@ -19,4 +19,10 @@ source:
ref: session ref: session
post: | post: |
.. versionadded:: 1.3 .. versionadded:: 1.3
---
source:
file: apiargs-MongoDBCollection-common-option.yaml
ref: typeMap
post: |
.. versionadded:: 1.5
... ...
...@@ -69,6 +69,8 @@ class Distinct implements Executable, Explainable ...@@ -69,6 +69,8 @@ class Distinct implements Executable, Explainable
* *
* Sessions are not supported for server versions < 3.6. * Sessions are not supported for server versions < 3.6.
* *
* * typeMap (array): Type map for BSON deserialization.
*
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
* @param string $fieldName Field for which to return distinct values * @param string $fieldName Field for which to return distinct values
...@@ -102,6 +104,10 @@ class Distinct implements Executable, Explainable ...@@ -102,6 +104,10 @@ class Distinct implements Executable, Explainable
throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
} }
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
}
if (isset($options['readConcern']) && $options['readConcern']->isDefault()) { if (isset($options['readConcern']) && $options['readConcern']->isDefault()) {
unset($options['readConcern']); unset($options['readConcern']);
} }
...@@ -139,6 +145,11 @@ class Distinct implements Executable, Explainable ...@@ -139,6 +145,11 @@ class Distinct implements Executable, Explainable
} }
$cursor = $server->executeReadCommand($this->databaseName, new Command($this->createCommandDocument()), $this->createOptions()); $cursor = $server->executeReadCommand($this->databaseName, new Command($this->createCommandDocument()), $this->createOptions());
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap(\MongoDB\create_field_path_type_map($this->options['typeMap'], 'values.$'));
}
$result = current($cursor->toArray()); $result = current($cursor->toArray());
if ( ! isset($result->values) || ! is_array($result->values)) { if ( ! isset($result->values) || ! is_array($result->values)) {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
namespace MongoDB\Tests\Operation; namespace MongoDB\Tests\Operation;
use MongoDB\Driver\BulkWrite;
use MongoDB\Operation\Distinct; use MongoDB\Operation\Distinct;
use MongoDB\Tests\CommandObserver; use MongoDB\Tests\CommandObserver;
use stdClass; use stdClass;
...@@ -51,4 +52,89 @@ class DistinctFunctionalTest extends FunctionalTestCase ...@@ -51,4 +52,89 @@ class DistinctFunctionalTest extends FunctionalTestCase
} }
); );
} }
/**
* @dataProvider provideTypeMapOptionsAndExpectedDocuments
*/
public function testTypeMapOption(array $typeMap, array $expectedDocuments)
{
$bulkWrite = new BulkWrite(['ordered' => true]);
$bulkWrite->insert([
'x' => (object) ['foo' => 'bar'],
]);
$bulkWrite->insert([
'x' => 4,
]);
$bulkWrite->insert([
'x' => (object) ['foo' => ['foo' => 'bar']],
]);
$this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite);
$distinct = new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', [], ['typeMap' => $typeMap]);
$values = $distinct->execute($this->getPrimaryServer());
/* This sort callable sorts all scalars to the front of the list. All
* non-scalar values are sorted by running json_encode on them and
* comparing their string representations.
*/
$sort = function ($a, $b) {
if (is_scalar($a) && ! is_scalar($b)) {
return -1;
}
if (! is_scalar($a)) {
if (is_scalar($b)) {
return 1;
}
$a = json_encode($a);
$b = json_encode($b);
}
return $a < $b ? -1 : 1;
};
usort($expectedDocuments, $sort);
usort($values, $sort);
$this->assertEquals($expectedDocuments, $values);
}
public function provideTypeMapOptionsAndExpectedDocuments()
{
return [
'No type map' => [
['root' => 'array', 'document' => 'array'],
[
['foo' => 'bar'],
4,
['foo' => ['foo' => 'bar']],
],
],
'array/array' => [
['root' => 'array', 'document' => 'array'],
[
['foo' => 'bar'],
4,
['foo' => ['foo' => 'bar']],
],
],
'object/array' => [
['root' => 'object', 'document' => 'array'],
[
(object) ['foo' => 'bar'],
4,
(object) ['foo' => ['foo' => 'bar']],
],
],
'array/stdClass' => [
['root' => 'array', 'document' => 'stdClass'],
[
['foo' => 'bar'],
4,
['foo' => (object) ['foo' => 'bar']],
],
],
];
}
} }
...@@ -49,6 +49,10 @@ class DistinctTest extends TestCase ...@@ -49,6 +49,10 @@ class DistinctTest extends TestCase
$options[][] = ['session' => $value]; $options[][] = ['session' => $value];
} }
foreach ($this->getInvalidArrayValues() as $value) {
$options[][] = ['typeMap' => $value];
}
return $options; return $options;
} }
} }
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