See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]
1 <?php 2 /* 3 * Copyright 2015-present 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 * https://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\Command; 21 use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException; 22 use MongoDB\Driver\ReadConcern; 23 use MongoDB\Driver\ReadPreference; 24 use MongoDB\Driver\Server; 25 use MongoDB\Driver\Session; 26 use MongoDB\Exception\InvalidArgumentException; 27 use MongoDB\Exception\UnexpectedValueException; 28 use MongoDB\Exception\UnsupportedException; 29 30 use function current; 31 use function is_array; 32 use function is_float; 33 use function is_integer; 34 use function is_object; 35 use function is_string; 36 37 /** 38 * Operation for the count command. 39 * 40 * @api 41 * @see \MongoDB\Collection::count() 42 * @see https://mongodb.com/docs/manual/reference/command/count/ 43 */ 44 class Count implements Executable, Explainable 45 { 46 /** @var string */ 47 private $databaseName; 48 49 /** @var string */ 50 private $collectionName; 51 52 /** @var array|object */ 53 private $filter; 54 55 /** @var array */ 56 private $options; 57 58 /** 59 * Constructs a count command. 60 * 61 * Supported options: 62 * 63 * * collation (document): Collation specification. 64 * 65 * * comment (mixed): BSON value to attach as a comment to this command. 66 * 67 * This is not supported for servers versions < 4.4. 68 * 69 * * hint (string|document): The index to use. Specify either the index 70 * name as a string or the index key pattern as a document. If specified, 71 * then the query system will only consider plans using the hinted index. 72 * 73 * * limit (integer): The maximum number of documents to count. 74 * 75 * * maxTimeMS (integer): The maximum amount of time to allow the query to 76 * run. 77 * 78 * * readConcern (MongoDB\Driver\ReadConcern): Read concern. 79 * 80 * * readPreference (MongoDB\Driver\ReadPreference): Read preference. 81 * 82 * * session (MongoDB\Driver\Session): Client session. 83 * 84 * * skip (integer): The number of documents to skip before returning the 85 * documents. 86 * 87 * @param string $databaseName Database name 88 * @param string $collectionName Collection name 89 * @param array|object $filter Query by which to filter documents 90 * @param array $options Command options 91 * @throws InvalidArgumentException for parameter/option parsing errors 92 */ 93 public function __construct(string $databaseName, string $collectionName, $filter = [], array $options = []) 94 { 95 if (! is_array($filter) && ! is_object($filter)) { 96 throw InvalidArgumentException::invalidType('$filter', $filter, 'array or object'); 97 } 98 99 if (isset($options['collation']) && ! is_array($options['collation']) && ! is_object($options['collation'])) { 100 throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object'); 101 } 102 103 if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) { 104 throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object'); 105 } 106 107 if (isset($options['limit']) && ! is_integer($options['limit'])) { 108 throw InvalidArgumentException::invalidType('"limit" option', $options['limit'], 'integer'); 109 } 110 111 if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { 112 throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); 113 } 114 115 if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) { 116 throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], ReadConcern::class); 117 } 118 119 if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { 120 throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); 121 } 122 123 if (isset($options['session']) && ! $options['session'] instanceof Session) { 124 throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); 125 } 126 127 if (isset($options['skip']) && ! is_integer($options['skip'])) { 128 throw InvalidArgumentException::invalidType('"skip" option', $options['skip'], 'integer'); 129 } 130 131 if (isset($options['readConcern']) && $options['readConcern']->isDefault()) { 132 unset($options['readConcern']); 133 } 134 135 $this->databaseName = $databaseName; 136 $this->collectionName = $collectionName; 137 $this->filter = $filter; 138 $this->options = $options; 139 } 140 141 /** 142 * Execute the operation. 143 * 144 * @see Executable::execute() 145 * @return integer 146 * @throws UnexpectedValueException if the command response was malformed 147 * @throws UnsupportedException if read concern is used and unsupported 148 * @throws DriverRuntimeException for other driver errors (e.g. connection errors) 149 */ 150 public function execute(Server $server) 151 { 152 $inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction(); 153 if ($inTransaction && isset($this->options['readConcern'])) { 154 throw UnsupportedException::readConcernNotSupportedInTransaction(); 155 } 156 157 $cursor = $server->executeReadCommand($this->databaseName, new Command($this->createCommandDocument()), $this->createOptions()); 158 $result = current($cursor->toArray()); 159 160 // Older server versions may return a float 161 if (! is_object($result) || ! isset($result->n) || ! (is_integer($result->n) || is_float($result->n))) { 162 throw new UnexpectedValueException('count command did not return a numeric "n" value'); 163 } 164 165 return (integer) $result->n; 166 } 167 168 /** 169 * Returns the command document for this operation. 170 * 171 * @see Explainable::getCommandDocument() 172 * @return array 173 */ 174 public function getCommandDocument(Server $server) 175 { 176 return $this->createCommandDocument(); 177 } 178 179 /** 180 * Create the count command document. 181 */ 182 private function createCommandDocument(): array 183 { 184 $cmd = ['count' => $this->collectionName]; 185 186 if (! empty($this->filter)) { 187 $cmd['query'] = (object) $this->filter; 188 } 189 190 if (isset($this->options['collation'])) { 191 $cmd['collation'] = (object) $this->options['collation']; 192 } 193 194 if (isset($this->options['hint'])) { 195 $cmd['hint'] = is_array($this->options['hint']) ? (object) $this->options['hint'] : $this->options['hint']; 196 } 197 198 foreach (['comment', 'limit', 'maxTimeMS', 'skip'] as $option) { 199 if (isset($this->options[$option])) { 200 $cmd[$option] = $this->options[$option]; 201 } 202 } 203 204 return $cmd; 205 } 206 207 /** 208 * Create options for executing the command. 209 * 210 * @see https://php.net/manual/en/mongodb-driver-server.executereadcommand.php 211 */ 212 private function createOptions(): array 213 { 214 $options = []; 215 216 if (isset($this->options['readConcern'])) { 217 $options['readConcern'] = $this->options['readConcern']; 218 } 219 220 if (isset($this->options['readPreference'])) { 221 $options['readPreference'] = $this->options['readPreference']; 222 } 223 224 if (isset($this->options['session'])) { 225 $options['session'] = $this->options['session']; 226 } 227 228 return $options; 229 } 230 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body