22
33namespace MongoDB ;
44
5+ use MongoDB \Driver \BulkWrite ;
56use MongoDB \Driver \Command ;
67use MongoDB \Driver \Cursor ;
78use MongoDB \Driver \Manager ;
89use MongoDB \Driver \Query ;
910use MongoDB \Driver \ReadPreference ;
10- use MongoDB \Driver \BulkWrite ;
11+ use MongoDB \Driver \Server ;
1112use MongoDB \Driver \WriteConcern ;
13+ use MongoDB \Exception \InvalidArgumentException ;
14+ use MongoDB \Exception \UnexpectedTypeException ;
15+ use MongoDB \Model \IndexInfoIterator ;
16+ use MongoDB \Model \IndexInfoIteratorIterator ;
17+ use MongoDB \Model \IndexInput ;
1218
1319class Collection
1420{
@@ -244,34 +250,68 @@ public function count(array $filter = array(), array $options = array())
244250 }
245251
246252 /**
247- * Create a single index in the collection.
253+ * Create a single index for the collection.
248254 *
249255 * @see http://docs.mongodb.org/manual/reference/command/createIndexes/
250256 * @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
251- * @param array|object $keys
252- * @param array $options
257+ * @see Collection::createIndexes()
258+ * @param array|object $key Document containing fields mapped to values,
259+ * which denote order or an index type
260+ * @param array $options Index options
253261 * @return string The name of the created index
254262 */
255- public function createIndex ($ keys , array $ options = array ())
263+ public function createIndex ($ key , array $ options = array ())
256264 {
257- // TODO
265+ return current ( $ this -> createIndexes ( array ( array ( ' key ' => $ key ) + $ options )));
258266 }
259267
260268 /**
261- * Create multiple indexes in the collection.
269+ * Create one or more indexes for the collection.
270+ *
271+ * Each element in the $indexes array must have a "key" document, which
272+ * contains fields mapped to an order or type. Other options may follow.
273+ * For example:
274+ *
275+ * $indexes = [
276+ * // Create a unique index on the "username" field
277+ * [ 'key' => [ 'username' => 1 ], 'unique' => true ],
278+ * // Create a 2dsphere index on the "loc" field with a custom name
279+ * [ 'key' => [ 'loc' => '2dsphere' ], 'name' => 'geo' ],
280+ * ];
262281 *
263- * TODO: decide if $models should be an array of associative arrays, using
264- * createIndex()'s parameter names as keys, or tuples, using parameters in
265- * order (e.g. [keys, options]).
282+ * If the "name" option is unspecified, a name will be generated from the
283+ * "key" document.
266284 *
267285 * @see http://docs.mongodb.org/manual/reference/command/createIndexes/
268286 * @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
269- * @param array $models
287+ * @param array $indexes List of index specifications
270288 * @return string[] The names of the created indexes
289+ * @throws InvalidArgumentException if an index specification is invalid
271290 */
272- public function createIndexes (array $ models )
291+ public function createIndexes (array $ indexes )
273292 {
274- // TODO
293+ if (empty ($ indexes )) {
294+ return array ();
295+ }
296+
297+ foreach ($ indexes as $ i => $ index ) {
298+ if ( ! is_array ($ index )) {
299+ throw new UnexpectedTypeException ($ index , 'array ' );
300+ }
301+
302+ if ( ! isset ($ index ['ns ' ])) {
303+ $ index ['ns ' ] = $ this ->ns ;
304+ }
305+
306+ $ indexes [$ i ] = new IndexInput ($ index );
307+ }
308+
309+ $ readPreference = new ReadPreference (ReadPreference::RP_PRIMARY );
310+ $ server = $ this ->manager ->selectServer ($ readPreference );
311+
312+ return (FeatureDetection::isSupported ($ server , FeatureDetection::API_CREATEINDEXES_CMD ))
313+ ? $ this ->createIndexesCommand ($ server , $ indexes )
314+ : $ this ->createIndexesLegacy ($ server , $ indexes );
275315 }
276316
277317 /**
@@ -354,11 +394,24 @@ public function drop()
354394 * @see http://docs.mongodb.org/manual/reference/method/db.collection.dropIndex/
355395 * @param string $indexName
356396 * @return Cursor
357- * @throws InvalidArgumentException if "*" is specified
397+ * @throws InvalidArgumentException if $indexName is an empty string or "*"
358398 */
359399 public function dropIndex ($ indexName )
360400 {
361- // TODO
401+ $ indexName = (string ) $ indexName ;
402+
403+ if ($ indexName === '' ) {
404+ throw new InvalidArgumentException ('Index name cannot be empty ' );
405+ }
406+
407+ if ($ indexName === '* ' ) {
408+ throw new InvalidArgumentException ('dropIndexes() must be used to drop multiple indexes ' );
409+ }
410+
411+ $ command = new Command (array ('dropIndexes ' => $ this ->collname , 'index ' => $ indexName ));
412+ $ readPreference = new ReadPreference (ReadPreference::RP_PRIMARY );
413+
414+ return $ this ->manager ->executeCommand ($ this ->dbname , $ command , $ readPreference );
362415 }
363416
364417 /**
@@ -370,7 +423,10 @@ public function dropIndex($indexName)
370423 */
371424 public function dropIndexes ()
372425 {
373- // TODO
426+ $ command = new Command (array ('dropIndexes ' => $ this ->collname , 'index ' => '* ' ));
427+ $ readPreference = new ReadPreference (ReadPreference::RP_PRIMARY );
428+
429+ return $ this ->manager ->executeCommand ($ this ->dbname , $ command , $ readPreference );
374430 }
375431
376432 /**
@@ -949,15 +1005,20 @@ public function insertOne(array $document)
9491005 }
9501006
9511007 /**
952- * Returns information for all indexes in the collection.
1008+ * Returns information for all indexes for the collection.
9531009 *
9541010 * @see http://docs.mongodb.org/manual/reference/command/listIndexes/
9551011 * @see http://docs.mongodb.org/manual/reference/method/db.collection.getIndexes/
956- * @return Cursor
1012+ * @return IndexInfoIterator
9571013 */
9581014 public function listIndexes ()
9591015 {
960- // TODO
1016+ $ readPreference = new ReadPreference (ReadPreference::RP_PRIMARY );
1017+ $ server = $ this ->manager ->selectServer ($ readPreference );
1018+
1019+ return (FeatureDetection::isSupported ($ server , FeatureDetection::API_LISTINDEXES_CMD ))
1020+ ? $ this ->listIndexesCommand ($ server )
1021+ : $ this ->listIndexesLegacy ($ server );
9611022 }
9621023
9631024 /**
@@ -1136,4 +1197,78 @@ protected function _update($filter, $update, $options)
11361197 $ bulk ->update ($ filter , $ update , $ options );
11371198 return $ this ->manager ->executeBulkWrite ($ this ->ns , $ bulk , $ this ->wc );
11381199 }
1200+
1201+ /**
1202+ * Create one or more indexes for the collection using the createIndexes
1203+ * command.
1204+ *
1205+ * @param Server $server
1206+ * @param IndexInput[] $indexes
1207+ * @return string[] The names of the created indexes
1208+ */
1209+ private function createIndexesCommand (Server $ server , array $ indexes )
1210+ {
1211+ $ command = new Command (array (
1212+ 'createIndexes ' => $ this ->collname ,
1213+ 'indexes ' => $ indexes ,
1214+ ));
1215+ $ server ->executeCommand ($ this ->dbname , $ command );
1216+
1217+ return array_map (function (IndexInput $ index ) { return (string ) $ index ; }, $ indexes );
1218+ }
1219+
1220+ /**
1221+ * Create one or more indexes for the collection by inserting into the
1222+ * "system.indexes" collection (MongoDB <2.6).
1223+ *
1224+ * @param Server $server
1225+ * @param IndexInput[] $indexes
1226+ * @return string[] The names of the created indexes
1227+ */
1228+ private function createIndexesLegacy (Server $ server , array $ indexes )
1229+ {
1230+ $ bulk = new BulkWrite (true );
1231+
1232+ foreach ($ indexes as $ index ) {
1233+ // TODO: Remove this once PHPC-274 is resolved (see: PHPLIB-87)
1234+ $ bulk ->insert ($ index ->bsonSerialize ());
1235+ }
1236+
1237+ $ server ->executeBulkWrite ($ this ->dbname . '.system.indexes ' , $ bulk );
1238+
1239+ return array_map (function (IndexInput $ index ) { return (string ) $ index ; }, $ indexes );
1240+ }
1241+
1242+ /**
1243+ * Returns information for all indexes for this collection using the
1244+ * listIndexes command.
1245+ *
1246+ * @see http://docs.mongodb.org/manual/reference/command/listIndexes/
1247+ * @param Server $server
1248+ * @return IndexInfoIteratorIterator
1249+ */
1250+ private function listIndexesCommand (Server $ server )
1251+ {
1252+ $ command = new Command (array ('listIndexes ' => $ this ->collname ));
1253+ $ cursor = $ server ->executeCommand ($ this ->dbname , $ command );
1254+ $ cursor ->setTypeMap (array ('document ' => 'array ' ));
1255+
1256+ return new IndexInfoIteratorIterator ($ cursor );
1257+ }
1258+
1259+ /**
1260+ * Returns information for all indexes for this collection by querying the
1261+ * "system.indexes" collection (MongoDB <2.8).
1262+ *
1263+ * @param Server $server
1264+ * @return IndexInfoIteratorIterator
1265+ */
1266+ private function listIndexesLegacy (Server $ server )
1267+ {
1268+ $ query = new Query (array ('ns ' => $ this ->ns ));
1269+ $ cursor = $ server ->executeQuery ($ this ->dbname . '.system.indexes ' , $ query );
1270+ $ cursor ->setTypeMap (array ('document ' => 'array ' ));
1271+
1272+ return new IndexInfoIteratorIterator ($ cursor );
1273+ }
11391274}
0 commit comments