Commit be6ba1e4 authored by Jeremy Mikola's avatar Jeremy Mikola

PHPLIB-285: Do not convert count's hint document to a string

parent 780fb6c3
......@@ -6,8 +6,13 @@ arg_name: option
name: hint
type: string|array|object
description: |
The index to use. If you specify a document, it is interpreted as an index
specification from which a name will be derived.
The index to use. Specify either the index name as a string or the index key
pattern as a document. If specified, then the query system will only consider
plans using the hinted index.
.. versionchanged:: 1.2
If a document is provided, it is passed to the command as-is. Previously,
the library would convert the key pattern to an index name.
interface: phpmethod
operation: ~
optional: true
......
......@@ -53,8 +53,9 @@ class Count implements Executable
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* * hint (string|document): The index to use. If a document, it will be
* interpretted as an index specification and a name will be generated.
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
* then the query system will only consider plans using the hinted index.
*
* * limit (integer): The maximum number of documents to count.
*
......@@ -87,14 +88,8 @@ class Count implements Executable
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
}
if (isset($options['hint'])) {
if (is_array($options['hint']) || is_object($options['hint'])) {
$options['hint'] = \MongoDB\generate_index_name($options['hint']);
}
if ( ! is_string($options['hint'])) {
throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object');
}
if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) {
throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object');
}
if (isset($options['limit']) && ! is_integer($options['limit'])) {
......@@ -177,7 +172,11 @@ class Count implements Executable
$cmd['collation'] = (object) $this->options['collation'];
}
foreach (['hint', 'limit', 'maxTimeMS', 'skip'] as $option) {
if (isset($this->options['hint'])) {
$cmd['hint'] = is_array($this->options['hint']) ? (object) $this->options['hint'] : $this->options['hint'];
}
foreach (['limit', 'maxTimeMS', 'skip'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
......
......@@ -3,6 +3,8 @@
namespace MongoDB\Tests\Operation;
use MongoDB\Operation\Count;
use MongoDB\Operation\CreateIndexes;
use MongoDB\Operation\InsertMany;
use MongoDB\Tests\CommandObserver;
use stdClass;
......@@ -26,4 +28,49 @@ class CountFunctionalTest extends FunctionalTestCase
}
);
}
public function testHintOption()
{
if (version_compare($this->getServerVersion(), '2.6.0', '<')) {
$this->markTestSkipped('count command does not support "hint" option');
}
$insertMany = new InsertMany($this->getDatabaseName(), $this->getCollectionName(), [
['x' => 1],
['x' => 2],
['y' => 3],
]);
$insertMany->execute($this->getPrimaryServer());
$createIndexes = new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), [
['key' => ['x' => 1], 'sparse' => true, 'name' => 'sparse_x'],
['key' => ['y' => 1]],
]);
$createIndexes->execute($this->getPrimaryServer());
$hintsUsingSparseIndex = [
['x' => 1],
'sparse_x',
];
/* Per SERVER-22041, the count command in server versions before 3.3.2
* may ignore the hint option if its query predicate is empty. */
$filter = ['_id' => ['$exists' => true]];
foreach ($hintsUsingSparseIndex as $hint) {
$operation = new Count($this->getDatabaseName(), $this->getCollectionName(), $filter, ['hint' => $hint]);
$this->assertEquals(2, $operation->execute($this->getPrimaryServer()));
}
$hintsNotUsingSparseIndex = [
['_id' => 1],
['y' => 1],
'y_1',
];
foreach ($hintsNotUsingSparseIndex as $hint) {
$operation = new Count($this->getDatabaseName(), $this->getCollectionName(), $filter, ['hint' => $hint]);
$this->assertEquals(3, $operation->execute($this->getPrimaryServer()));
}
}
}
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