Differences Between: [Versions 310 and 401]
1 <?php 2 /* 3 * Copyright 2015-2017 MongoDB, Inc. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 namespace MongoDB\Operation; 19 20 use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException; 21 use MongoDB\Driver\Server; 22 use MongoDB\Exception\InvalidArgumentException; 23 use MongoDB\Exception\UnexpectedValueException; 24 use MongoDB\Exception\UnsupportedException; 25 use function array_intersect_key; 26 use function count; 27 use function current; 28 use function is_array; 29 use function is_float; 30 use function is_integer; 31 use function is_object; 32 33 /** 34 * Operation for obtaining an exact count of documents in a collection 35 * 36 * @api 37 * @see \MongoDB\Collection::countDocuments() 38 * @see https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#countdocuments 39 */ 40 class CountDocuments implements Executable 41 { 42 /** @var string */ 43 private $databaseName; 44 45 /** @var string */ 46 private $collectionName; 47 48 /** @var array|object */ 49 private $filter; 50 51 /** @var array */ 52 private $aggregateOptions; 53 54 /** @var array */ 55 private $countOptions; 56 57 /** @var Aggregate */ 58 private $aggregate; 59 60 /** 61 * Constructs an aggregate command for counting documents 62 * 63 * Supported options: 64 * 65 * * collation (document): Collation specification. 66 * 67 * This is not supported for server versions < 3.4 and will result in an 68 * exception at execution time if used. 69 * 70 * * hint (string|document): The index to use. Specify either the index 71 * name as a string or the index key pattern as a document. If specified, 72 * then the query system will only consider plans using the hinted index. 73 * 74 * * limit (integer): The maximum number of documents to count. 75 * 76 * * maxTimeMS (integer): The maximum amount of time to allow the query to 77 * run. 78 * 79 * * readConcern (MongoDB\Driver\ReadConcern): Read concern. 80 * 81 * This is not supported for server versions < 3.2 and will result in an 82 * exception at execution time if used. 83 * 84 * * readPreference (MongoDB\Driver\ReadPreference): Read preference. 85 * 86 * * session (MongoDB\Driver\Session): Client session. 87 * 88 * Sessions are not supported for server versions < 3.6. 89 * 90 * * skip (integer): The number of documents to skip before returning the 91 * documents. 92 * 93 * @param string $databaseName Database name 94 * @param string $collectionName Collection name 95 * @param array|object $filter Query by which to filter documents 96 * @param array $options Command options 97 * @throws InvalidArgumentException for parameter/option parsing errors 98 */ 99 public function __construct($databaseName, $collectionName, $filter, array $options = []) 100 { 101 if (! is_array($filter) && ! is_object($filter)) { 102 throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object'); 103 } 104 105 if (isset($options['limit']) && ! is_integer($options['limit'])) { 106 throw InvalidArgumentException::invalidType('"limit" option', $options['limit'], 'integer'); 107 } 108 109 if (isset($options['skip']) && ! is_integer($options['skip'])) { 110 throw InvalidArgumentException::invalidType('"skip" option', $options['skip'], 'integer'); 111 } 112 113 $this->databaseName = (string) $databaseName; 114 $this->collectionName = (string) $collectionName; 115 $this->filter = $filter; 116 117 $this->aggregateOptions = array_intersect_key($options, ['collation' => 1, 'hint' => 1, 'maxTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1]); 118 $this->countOptions = array_intersect_key($options, ['limit' => 1, 'skip' => 1]); 119 120 $this->aggregate = $this->createAggregate(); 121 } 122 123 /** 124 * Execute the operation. 125 * 126 * @see Executable::execute() 127 * @param Server $server 128 * @return integer 129 * @throws UnexpectedValueException if the command response was malformed 130 * @throws UnsupportedException if collation or read concern is used and unsupported 131 * @throws DriverRuntimeException for other driver errors (e.g. connection errors) 132 */ 133 public function execute(Server $server) 134 { 135 $cursor = $this->aggregate->execute($server); 136 $allResults = $cursor->toArray(); 137 138 /* If there are no documents to count, the aggregation pipeline has no items to group, and 139 * hence the result is an empty array (PHPLIB-376) */ 140 if (count($allResults) == 0) { 141 return 0; 142 } 143 144 $result = current($allResults); 145 if (! isset($result->n) || ! (is_integer($result->n) || is_float($result->n))) { 146 throw new UnexpectedValueException('count command did not return a numeric "n" value'); 147 } 148 149 return (integer) $result->n; 150 } 151 152 /** 153 * @return Aggregate 154 */ 155 private function createAggregate() 156 { 157 $pipeline = [ 158 ['$match' => (object) $this->filter], 159 ]; 160 161 if (isset($this->countOptions['skip'])) { 162 $pipeline[] = ['$skip' => $this->countOptions['skip']]; 163 } 164 165 if (isset($this->countOptions['limit'])) { 166 $pipeline[] = ['$limit' => $this->countOptions['limit']]; 167 } 168 169 $pipeline[] = ['$group' => ['_id' => 1, 'n' => ['$sum' => 1]]]; 170 171 return new Aggregate($this->databaseName, $this->collectionName, $pipeline, $this->aggregateOptions); 172 } 173 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body