Commit e36a304c authored by Jeremy Mikola's avatar Jeremy Mikola

Extract Collection::count() to an operation class

parent 5b7bb9a4
...@@ -17,6 +17,7 @@ use MongoDB\Model\IndexInfoIteratorIterator; ...@@ -17,6 +17,7 @@ use MongoDB\Model\IndexInfoIteratorIterator;
use MongoDB\Model\IndexInput; use MongoDB\Model\IndexInput;
use MongoDB\Operation\Aggregate; use MongoDB\Operation\Aggregate;
use MongoDB\Operation\CreateIndexes; use MongoDB\Operation\CreateIndexes;
use MongoDB\Operation\Count;
use MongoDB\Operation\Distinct; use MongoDB\Operation\Distinct;
use Traversable; use Traversable;
...@@ -236,28 +237,19 @@ class Collection ...@@ -236,28 +237,19 @@ class Collection
} }
/** /**
* Counts all documents matching $filter * Gets the number of documents matching the filter.
* If no $filter provided, returns the numbers of documents in the collection
* *
* @see http://docs.mongodb.org/manual/reference/command/count/ * @see Count::__construct() for supported options
* @see Collection::getCountOptions() for supported $options * @param array $filter Query by which to filter documents
* * @param array $options Command options
* @param array $filter The find query to execute
* @param array $options Additional options
* @return integer * @return integer
*/ */
public function count(array $filter = array(), array $options = array()) public function count(array $filter = array(), array $options = array())
{ {
$cmd = array( $operation = new Count($this->dbname, $this->collname, $filter, $options);
"count" => $this->collname, $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
"query" => (object) $filter,
) + $options;
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray()); return $operation->execute($server);
if ($doc["ok"]) {
return (integer) $doc["n"];
}
throw $this->_generateCommandException($doc);
} }
/** /**
...@@ -581,44 +573,6 @@ class Collection ...@@ -581,44 +573,6 @@ class Collection
return $this->collname; return $this->collname;
} }
/**
* Retrieves all count options with their default values.
*
* @return array of Collection::count() options
*/
public function getCountOptions()
{
return array(
/**
* The index to use.
*
* @see http://docs.mongodb.org/manual/reference/command/count/
*/
"hint" => "", // string or document
/**
* The maximum number of documents to count.
*
* @see http://docs.mongodb.org/manual/reference/command/count/
*/
"limit" => 0,
/**
* The maximum amount of time to allow the query to run.
*
* @see http://docs.mongodb.org/manual/reference/command/count/
*/
"maxTimeMS" => 0,
/**
* The number of documents to skip before returning the documents.
*
* @see http://docs.mongodb.org/manual/reference/command/count/
*/
"skip" => 0,
);
}
/** /**
* Return the database name. * Return the database name.
* *
......
<?php
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
use MongoDB\Exception\RuntimeException;
use MongoDB\Exception\UnexpectedValueException;
/**
* Operation for the count command.
*
* @api
* @see MongoDB\Collection::count()
* @see http://docs.mongodb.org/manual/reference/command/count/
*/
class Count implements Executable
{
private $databaseName;
private $collectionName;
private $filter;
private $options;
/**
* Constructs a count command.
*
* Supported options:
*
* * hint (string|document): The index to use. If a document, it will be
* interpretted as an index specification and a name will be generated.
*
* * limit (integer): The maximum number of documents to count.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * skip (integer): The number of documents to skip before returning the
* documents.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array $filter Query by which to filter documents
* @param array $options Command options
* @throws InvalidArgumentException
*/
public function __construct($databaseName, $collectionName, array $filter = array(), array $options = array())
{
if (isset($options['hint'])) {
if (is_array($options['hint']) || is_object($options['hint'])) {
$options['hint'] = $this->generateIndexName($options['hint']);
}
if ( ! is_string($options['hint'])) {
throw new InvalidArgumentTypeException('"hint" option', $options['hint'], 'string or array or object');
}
}
if (isset($options['limit']) && ! is_integer($options['limit'])) {
throw new InvalidArgumentTypeException('"limit" option', $options['limit'], 'integer');
}
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw new InvalidArgumentTypeException('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if (isset($options['skip']) && ! is_integer($options['skip'])) {
throw new InvalidArgumentTypeException('"skip" option', $options['skip'], 'integer');
}
$this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName;
$this->filter = $filter;
$this->options = $options;
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return integer
*/
public function execute(Server $server)
{
$cursor = $server->executeCommand($this->databaseName, $this->createCommand());
$result = current($cursor->toArray());
if (empty($result['ok'])) {
throw new RuntimeException(isset($result['errmsg']) ? $result['errmsg'] : 'Unknown error');
}
if ( ! isset($result['n']) || ! is_integer($result['n'])) {
throw new UnexpectedValueException('count command did not return an "n" integer');
}
return $result['n'];
}
/**
* Create the count command.
*
* @return Command
*/
private function createCommand()
{
$cmd = array(
'count' => $this->collectionName,
);
if ( ! empty($this->filter)) {
$cmd['query'] = (object) $this->filter;
}
foreach (array('hint', 'limit', 'maxTimeMS', 'skip') as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
return new Command($cmd);
}
/**
* Generates an index name from its key specification.
*
* @param array|object $key Document containing fields mapped to values,
* which denote order or an index type
* @return string
*/
private function generateIndexName($key)
{
$name = '';
foreach ($key as $field => $type) {
$name .= ($name != '' ? '_' : '') . $field . '_' . $type;
}
return $name;
}
}
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