Skip to content

Commit 9f947d9

Browse files
committed
Extract Collection::distinct() to an operation class
1 parent 03eb7c8 commit 9f947d9

File tree

2 files changed

+110
-36
lines changed

2 files changed

+110
-36
lines changed

src/Collection.php

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use MongoDB\Model\IndexInfoIteratorIterator;
1717
use MongoDB\Model\IndexInput;
1818
use MongoDB\Operation\Aggregate;
19+
use MongoDB\Operation\Distinct;
1920
use Traversable;
2021

2122
class Collection
@@ -356,30 +357,20 @@ public function deleteOne(array $filter)
356357
}
357358

358359
/**
359-
* Finds the distinct values for a specified field across the collection
360+
* Finds the distinct values for a specified field across the collection.
360361
*
361-
* @see http://docs.mongodb.org/manual/reference/command/distinct/
362-
* @see Collection::getDistinctOptions() for supported $options
363-
*
364-
* @param string $fieldName The fieldname to use
365-
* @param array $filter The find query to execute
366-
* @param array $options Additional options
367-
* @return integer
362+
* @see Distinct::__construct() for supported options
363+
* @param string $fieldName Field for which to return distinct values
364+
* @param array $filter Query by which to filter documents
365+
* @param array $options Command options
366+
* @return mixed[]
368367
*/
369368
public function distinct($fieldName, array $filter = array(), array $options = array())
370369
{
371-
$options = array_merge($this->getDistinctOptions(), $options);
372-
$cmd = array(
373-
"distinct" => $this->collname,
374-
"key" => $fieldName,
375-
"query" => (object) $filter,
376-
) + $options;
370+
$operation = new Distinct($this->dbname, $this->collname, $fieldName, $filter, $options);
371+
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
377372

378-
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
379-
if ($doc["ok"]) {
380-
return $doc["values"];
381-
}
382-
throw $this->_generateCommandException($doc);
373+
return $operation->execute($server);
383374
}
384375

385376
/**
@@ -657,23 +648,6 @@ public function getDatabaseName()
657648
return $this->dbname;
658649
}
659650

660-
/**
661-
* Retrieves all distinct options with their default values.
662-
*
663-
* @return array of Collection::distinct() options
664-
*/
665-
public function getDistinctOptions()
666-
{
667-
return array(
668-
/**
669-
* The maximum amount of time to allow the query to run. The default is infinite.
670-
*
671-
* @see http://docs.mongodb.org/manual/reference/command/distinct/
672-
*/
673-
"maxTimeMS" => 0,
674-
);
675-
}
676-
677651
/**
678652
* Retrieves all findOneDelete options with their default values.
679653
*

src/Operation/Distinct.php

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
namespace MongoDB\Operation;
4+
5+
use MongoDB\Driver\Command;
6+
use MongoDB\Driver\Server;
7+
use MongoDB\Exception\InvalidArgumentException;
8+
use MongoDB\Exception\InvalidArgumentTypeException;
9+
use MongoDB\Exception\RuntimeException;
10+
use MongoDB\Exception\UnexpectedValueException;
11+
12+
/**
13+
* Operation for the distinct command.
14+
*
15+
* @api
16+
* @see MongoDB\Collection::distinct()
17+
* @see http://docs.mongodb.org/manual/reference/command/distinct/
18+
*/
19+
class Distinct implements Executable
20+
{
21+
private $databaseName;
22+
private $collectionName;
23+
private $fieldName;
24+
private $filter;
25+
private $options;
26+
27+
/**
28+
* Constructs a distinct command.
29+
*
30+
* Supported options:
31+
*
32+
* * maxTimeMS (integer): The maximum amount of time to allow the query to
33+
* run.
34+
*
35+
* @param string $databaseName Database name
36+
* @param string $collectionName Collection name
37+
* @param string $fieldName Field for which to return distinct values
38+
* @param array $filter Query by which to filter documents
39+
* @param array $options Command options
40+
* @throws InvalidArgumentException
41+
*/
42+
public function __construct($databaseName, $collectionName, $fieldName, array $filter = array(), array $options = array())
43+
{
44+
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
45+
throw new InvalidArgumentTypeException('maxTimeMS option', $options['maxTimeMS'], 'integer');
46+
}
47+
48+
$this->databaseName = (string) $databaseName;
49+
$this->collectionName = (string) $collectionName;
50+
$this->fieldName = (string) $fieldName;
51+
$this->filter = $filter;
52+
$this->options = $options;
53+
}
54+
55+
/**
56+
* Execute the operation.
57+
*
58+
* @see Executable::execute()
59+
* @param Server $server
60+
* @return mixed[]
61+
*/
62+
public function execute(Server $server)
63+
{
64+
$cursor = $server->executeCommand($this->databaseName, $this->createCommand());
65+
$result = current($cursor->toArray());
66+
67+
if (empty($result['ok'])) {
68+
throw new RuntimeException(isset($result['errmsg']) ? $result['errmsg'] : 'Unknown error');
69+
}
70+
71+
if ( ! isset($result['values']) || ! is_array($result['values'])) {
72+
throw new UnexpectedValueException('distinct command did not return a "values" array');
73+
}
74+
75+
return $result['values'];
76+
}
77+
78+
/**
79+
* Create the distinct command.
80+
*
81+
* @return Command
82+
*/
83+
private function createCommand()
84+
{
85+
$cmd = array(
86+
'distinct' => $this->collectionName,
87+
'key' => $this->fieldName,
88+
);
89+
90+
if ( ! empty($this->filter)) {
91+
$cmd['query'] = (object) $this->filter;
92+
}
93+
94+
if (isset($this->options['maxTimeMS'])) {
95+
$cmd[$option] = $this->options['maxTimeMS'];
96+
}
97+
98+
return new Command($cmd);
99+
}
100+
}

0 commit comments

Comments
 (0)