Skip to content

Commit 252c54e

Browse files
committed
Extract Collection::createIndexes() to an operation class
Additionally, this changes createIndexes() to no longer allow an empty array as input. The index management spec doesn't state that empty input must be accepted, so I'm not sure why we had that behavior.
1 parent 9f947d9 commit 252c54e

File tree

3 files changed

+128
-65
lines changed

3 files changed

+128
-65
lines changed

src/Collection.php

Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use MongoDB\Model\IndexInfoIteratorIterator;
1717
use MongoDB\Model\IndexInput;
1818
use MongoDB\Operation\Aggregate;
19+
use MongoDB\Operation\CreateIndexes;
1920
use MongoDB\Operation\Distinct;
2021
use Traversable;
2122

@@ -262,8 +263,6 @@ public function count(array $filter = array(), array $options = array())
262263
/**
263264
* Create a single index for the collection.
264265
*
265-
* @see http://docs.mongodb.org/manual/reference/command/createIndexes/
266-
* @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
267266
* @see Collection::createIndexes()
268267
* @param array|object $key Document containing fields mapped to values,
269268
* which denote order or an index type
@@ -294,34 +293,16 @@ public function createIndex($key, array $options = array())
294293
*
295294
* @see http://docs.mongodb.org/manual/reference/command/createIndexes/
296295
* @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
297-
* @param array $indexes List of index specifications
296+
* @param array[] $indexes List of index specifications
298297
* @return string[] The names of the created indexes
299298
* @throws InvalidArgumentException if an index specification is invalid
300299
*/
301300
public function createIndexes(array $indexes)
302301
{
303-
if (empty($indexes)) {
304-
return array();
305-
}
306-
307-
foreach ($indexes as $i => $index) {
308-
if ( ! is_array($index)) {
309-
throw new UnexpectedTypeException($index, 'array');
310-
}
311-
312-
if ( ! isset($index['ns'])) {
313-
$index['ns'] = $this->ns;
314-
}
315-
316-
$indexes[$i] = new IndexInput($index);
317-
}
318-
319-
$readPreference = new ReadPreference(ReadPreference::RP_PRIMARY);
320-
$server = $this->manager->selectServer($readPreference);
302+
$operation = new CreateIndexes($this->dbname, $this->collname, $indexes);
303+
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
321304

322-
return (FeatureDetection::isSupported($server, FeatureDetection::API_CREATEINDEXES_CMD))
323-
? $this->createIndexesCommand($server, $indexes)
324-
: $this->createIndexesLegacy($server, $indexes);
305+
return $operation->execute($server);
325306
}
326307

327308
/**
@@ -1184,46 +1165,6 @@ protected function _update($filter, $update, $options)
11841165
return $this->manager->executeBulkWrite($this->ns, $bulk, $this->wc);
11851166
}
11861167

1187-
/**
1188-
* Create one or more indexes for the collection using the createIndexes
1189-
* command.
1190-
*
1191-
* @param Server $server
1192-
* @param IndexInput[] $indexes
1193-
* @return string[] The names of the created indexes
1194-
*/
1195-
private function createIndexesCommand(Server $server, array $indexes)
1196-
{
1197-
$command = new Command(array(
1198-
'createIndexes' => $this->collname,
1199-
'indexes' => $indexes,
1200-
));
1201-
$server->executeCommand($this->dbname, $command);
1202-
1203-
return array_map(function(IndexInput $index) { return (string) $index; }, $indexes);
1204-
}
1205-
1206-
/**
1207-
* Create one or more indexes for the collection by inserting into the
1208-
* "system.indexes" collection (MongoDB <2.6).
1209-
*
1210-
* @param Server $server
1211-
* @param IndexInput[] $indexes
1212-
* @return string[] The names of the created indexes
1213-
*/
1214-
private function createIndexesLegacy(Server $server, array $indexes)
1215-
{
1216-
$bulk = new BulkWrite(true);
1217-
1218-
foreach ($indexes as $index) {
1219-
$bulk->insert($index);
1220-
}
1221-
1222-
$server->executeBulkWrite($this->dbname . '.system.indexes', $bulk);
1223-
1224-
return array_map(function(IndexInput $index) { return (string) $index; }, $indexes);
1225-
}
1226-
12271168
/**
12281169
* Returns information for all indexes for this collection using the
12291170
* listIndexes command.

src/Operation/CreateIndexes.php

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
namespace MongoDB\Operation;
4+
5+
use MongoDB\FeatureDetection;
6+
use MongoDB\Driver\Command;
7+
use MongoDB\Driver\Server;
8+
use MongoDB\Driver\BulkWrite;
9+
use MongoDB\Exception\InvalidArgumentException;
10+
use MongoDB\Exception\RuntimeException;
11+
use MongoDB\Exception\UnexpectedTypeException;
12+
use MongoDB\Model\IndexInput;
13+
14+
/**
15+
* Operation for the createIndexes command.
16+
*
17+
* @api
18+
* @see MongoDB\Collection::createIndex()
19+
* @see MongoDB\Collection::createIndexes()
20+
* @see http://docs.mongodb.org/manual/reference/command/createIndexes/
21+
*/
22+
class CreateIndexes implements Executable
23+
{
24+
private static $wireVersionForCommand = 2;
25+
26+
private $databaseName;
27+
private $collectionName;
28+
private $indexes = array();
29+
30+
/**
31+
* Constructs a createIndexes command.
32+
*
33+
* @param string $databaseName Database name
34+
* @param string $collectionName Collection name
35+
* @param array[] $indexes List of index specifications
36+
* @throws InvalidArgumentException
37+
*/
38+
public function __construct($databaseName, $collectionName, array $indexes)
39+
{
40+
if (empty($indexes)) {
41+
throw new InvalidArgumentException('$indexes is empty');
42+
}
43+
44+
foreach ($indexes as $index) {
45+
if ( ! is_array($index)) {
46+
throw new UnexpectedTypeException($index, 'array');
47+
}
48+
49+
if ( ! isset($index['ns'])) {
50+
$index['ns'] = $databaseName . '.' . $collectionName;
51+
}
52+
53+
$this->indexes[] = new IndexInput($index);
54+
}
55+
56+
$this->databaseName = (string) $databaseName;
57+
$this->collectionName = (string) $collectionName;
58+
}
59+
60+
/**
61+
* Execute the operation.
62+
*
63+
* For servers < 2.6, this will actually perform an insert operation on the
64+
* database's "system.indexes" collection.
65+
*
66+
* @see Executable::execute()
67+
* @param Server $server
68+
* @return string[] The names of the created indexes
69+
*/
70+
public function execute(Server $server)
71+
{
72+
if (FeatureDetection::isSupported($server, self::$wireVersionForCommand)) {
73+
$this->executeCommand($server);
74+
} else {
75+
$this->executeLegacy($server);
76+
}
77+
78+
return array_map(function(IndexInput $index) { return (string) $index; }, $this->indexes);
79+
}
80+
81+
/**
82+
* Create one or more indexes for the collection using the createIndexes
83+
* command.
84+
*
85+
* @param Server $server
86+
*/
87+
private function executeCommand(Server $server)
88+
{
89+
$command = new Command(array(
90+
'createIndexes' => $this->collectionName,
91+
'indexes' => $this->indexes,
92+
));
93+
94+
$cursor = $server->executeCommand($this->databaseName, $command);
95+
$result = current($cursor->toArray());
96+
97+
if (empty($result['ok'])) {
98+
throw new RuntimeException(isset($result['errmsg']) ? $result['errmsg'] : 'Unknown error');
99+
}
100+
}
101+
102+
/**
103+
* Create one or more indexes for the collection by inserting into the
104+
* "system.indexes" collection (MongoDB <2.6).
105+
*
106+
* @param Server $server
107+
* @param IndexInput[] $indexes
108+
*/
109+
private function executeLegacy(Server $server, array $indexes)
110+
{
111+
$bulk = new BulkWrite(true);
112+
113+
foreach ($this->indexes as $index) {
114+
$bulk->insert($index);
115+
}
116+
117+
$server->executeBulkWrite($this->databaseName . '.system.indexes', $bulk);
118+
}
119+
}

tests/Collection/IndexManagementFunctionalTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ public function testCreateIndexes()
8585
});
8686
}
8787

88-
public function testCreateIndexesWithEmptyInputIsNop()
88+
/**
89+
* @expectedException MongoDB\Exception\InvalidArgumentException
90+
*/
91+
public function testCreateIndexesRequiresAtLeastOneIndex()
8992
{
9093
$this->assertSame(array(), $this->collection->createIndexes(array()));
9194
}

0 commit comments

Comments
 (0)