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