Skip to content

Commit b41fa95

Browse files
committed
wip
1 parent 5d1686f commit b41fa95

File tree

5 files changed

+284
-11
lines changed

5 files changed

+284
-11
lines changed

src/BulkWriteResult.php

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
namespace MongoDB;
4+
5+
use BSON\ObjectId;
6+
use MongoDB\Driver\WriteResult;
7+
8+
/**
9+
* Result class for a bulk write operation.
10+
*/
11+
class BulkWriteResult
12+
{
13+
private $writeResult;
14+
private $insertedIds;
15+
16+
/**
17+
* Constructor.
18+
*
19+
* @param WriteResult $writeResult
20+
* @param mixed[] $insertedIds
21+
*/
22+
public function __construct(WriteResult $writeResult, array $insertedIds = array())
23+
{
24+
$this->writeResult = $writeResult;
25+
$this->insertedIds = $insertedIds;
26+
}
27+
28+
/**
29+
* Return the number of documents that were deleted.
30+
*
31+
* This value is undefined if the write was not acknowledged.
32+
*
33+
* @see BulkWriteResult::isAcknowledged()
34+
* @return integer
35+
*/
36+
public function getDeletedCount()
37+
{
38+
return $this->writeResult->getDeletedCount();
39+
}
40+
41+
/**
42+
* Return the number of documents that were inserted.
43+
*
44+
* This value is undefined if the write was not acknowledged.
45+
*
46+
* @see BulkWriteResult::isAcknowledged()
47+
* @return integer
48+
*/
49+
public function getInsertedCount()
50+
{
51+
return $this->writeResult->getInsertedCount();
52+
}
53+
54+
/**
55+
* Return a map of the inserted documents' IDs.
56+
*
57+
* The index of each ID in the map corresponds to the document's position
58+
* in bulk operation. If the document already an ID prior to insertion (i.e.
59+
* the driver did not need to generate an ID), this will contain its "_id".
60+
* Any driver-generated ID will be an MongoDB\Driver\ObjectID instance.
61+
*
62+
* @return mixed[]
63+
*/
64+
public function getInsertedIds()
65+
{
66+
return $this->insertedIds;
67+
}
68+
69+
/**
70+
* Return the number of documents that were matched by the filter.
71+
*
72+
* This value is undefined if the write was not acknowledged.
73+
*
74+
* @see BulkWriteResult::isAcknowledged()
75+
* @return integer
76+
*/
77+
public function getMatchedCount()
78+
{
79+
return $this->writeResult->getMatchedCount();
80+
}
81+
82+
/**
83+
* Return the number of documents that were modified.
84+
*
85+
* This value is undefined if the write was not acknowledged or if the write
86+
* executed as a legacy operation instead of write command.
87+
*
88+
* @see BulkWriteResult::isAcknowledged()
89+
* @return integer|null
90+
*/
91+
public function getModifiedCount()
92+
{
93+
return $this->writeResult->getModifiedCount();
94+
}
95+
96+
/**
97+
* Return the number of documents that were upserted.
98+
*
99+
* This value is undefined if the write was not acknowledged.
100+
*
101+
* @see BulkWriteResult::isAcknowledged()
102+
* @return integer
103+
*/
104+
public function getUpsertedCount()
105+
{
106+
return $this->writeResult->getUpsertedCount();
107+
}
108+
109+
/**
110+
* Return a map of the upserted documents' IDs.
111+
*
112+
* The index of each ID in the map corresponds to the document's position
113+
* in bulk operation. If the document had an ID prior to upserting (i.e. the
114+
* server did not need to generate an ID), this will contain its "_id". Any
115+
* server-generated ID will be an MongoDB\Driver\ObjectID instance.
116+
*
117+
* @return ObjectId|null
118+
*/
119+
public function getUpsertedIds()
120+
{
121+
return $this->writeResult->getUpsertedIds();
122+
}
123+
124+
/**
125+
* Return whether this update was acknowledged by the server.
126+
*
127+
* If the update was not acknowledged, other fields from the WriteResult
128+
* (e.g. matchedCount) will be undefined.
129+
*
130+
* @return boolean
131+
*/
132+
public function isAcknowledged()
133+
{
134+
return $this->writeResult->isAcknowledged();
135+
}
136+
}

src/Collection.php

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -198,32 +198,40 @@ function (\stdClass $document) { return (array) $document; },
198198
*
199199
* @see Collection::getBulkOptions() for supported $options
200200
*
201-
* @param array $bulk Array of operations
201+
* @param array $ops Array of operations
202202
* @param array $options Additional options
203203
* @return WriteResult
204204
*/
205-
public function bulkWrite(array $bulk, array $options = array())
205+
public function bulkWrite(array $ops, array $options = array())
206206
{
207207
$options = array_merge($this->getBulkOptions(), $options);
208208

209209
$bulk = new BulkWrite($options["ordered"]);
210+
$insertedIds = array();
210211

211-
foreach ($bulk as $n => $op) {
212+
foreach ($ops as $n => $op) {
212213
foreach ($op as $opname => $args) {
213214
if (!isset($args[0])) {
214215
throw new InvalidArgumentException(sprintf("Missing argument#1 for '%s' (operation#%d)", $opname, $n));
215216
}
216217

217218
switch ($opname) {
218219
case "insertOne":
219-
$bulk->insert($args[0]);
220+
$insertedId = $bulk->insert($args[0]);
221+
222+
if ($insertedId !== null) {
223+
$insertedIds[$n] = $insertedId;
224+
} else {
225+
$insertedIds[$n] = is_array($args[0]) ? $args[0]['_id'] : $args[0]->_id;
226+
}
227+
220228
break;
221229

222230
case "updateMany":
223231
if (!isset($args[1])) {
224232
throw new InvalidArgumentException(sprintf("Missing argument#2 for '%s' (operation#%d)", $opname, $n));
225233
}
226-
$options = array_merge($this->getWriteOptions(), isset($args[2]) ? $args[2] : array(), array("limit" => 0));
234+
$options = array_merge($this->getWriteOptions(), isset($args[2]) ? $args[2] : array(), array("multi" => true));
227235

228236
$bulk->update($args[0], $args[1], $options);
229237
break;
@@ -232,7 +240,7 @@ public function bulkWrite(array $bulk, array $options = array())
232240
if (!isset($args[1])) {
233241
throw new InvalidArgumentException(sprintf("Missing argument#2 for '%s' (operation#%d)", $opname, $n));
234242
}
235-
$options = array_merge($this->getWriteOptions(), isset($args[2]) ? $args[2] : array(), array("limit" => 1));
243+
$options = array_merge($this->getWriteOptions(), isset($args[2]) ? $args[2] : array(), array("multi" => false));
236244
$firstKey = key($args[1]);
237245
if (!isset($firstKey[0]) || $firstKey[0] != '$') {
238246
throw new InvalidArgumentException("First key in \$update must be a \$operator");
@@ -245,7 +253,7 @@ public function bulkWrite(array $bulk, array $options = array())
245253
if (!isset($args[1])) {
246254
throw new InvalidArgumentException(sprintf("Missing argument#2 for '%s' (operation#%d)", $opname, $n));
247255
}
248-
$options = array_merge($this->getWriteOptions(), isset($args[2]) ? $args[2] : array(), array("limit" => 1));
256+
$options = array_merge($this->getWriteOptions(), isset($args[2]) ? $args[2] : array(), array("multi" => false));
249257
$firstKey = key($args[1]);
250258
if (isset($firstKey[0]) && $firstKey[0] == '$') {
251259
throw new InvalidArgumentException("First key in \$update must NOT be a \$operator");
@@ -269,7 +277,10 @@ public function bulkWrite(array $bulk, array $options = array())
269277
}
270278
}
271279
}
272-
return $this->manager->executeBulkWrite($this->ns, $bulk, $this->wc);
280+
281+
$writeResult = $this->manager->executeBulkWrite($this->ns, $bulk, $this->wc);
282+
283+
return new BulkWriteResult($writeResult, $insertedIds);
273284
}
274285

275286
/**

src/InsertManyResult.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ public function getInsertedCount()
4141
* Return a map of the inserted documents' IDs.
4242
*
4343
* The index of each ID in the map corresponds to the document's position
44-
* in bulk operation. If the document already an ID prior to insertion (i.e.
45-
* the driver did not need to generate an ID), this will contain its "_id".
46-
* Any driver-generated ID will be an MongoDB\Driver\ObjectID instance.
44+
* in bulk operation. If the document had an ID prior to insertion (i.e. the
45+
* driver did not need to generate an ID), this will contain its "_id". Any
46+
* driver-generated ID will be an MongoDB\Driver\ObjectID instance.
4747
*
4848
* @return mixed[]
4949
*/

src/UpdateResult.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ public function getModifiedCount()
4949
return $this->writeResult->getModifiedCount();
5050
}
5151

52+
/**
53+
* Return the number of documents that were upserted.
54+
*
55+
* This value is undefined if the write was not acknowledged.
56+
*
57+
* @see UpdateResult::isAcknowledged()
58+
* @return integer
59+
*/
60+
public function getUpsertedCount()
61+
{
62+
return $this->writeResult->getUpsertedCount();
63+
}
64+
5265
/**
5366
* Return the ID of the document inserted by an upsert operation.
5467
*
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\Collection;
4+
5+
use MongoDB\BulkWriteResult;
6+
use MongoDB\Driver\BulkWrite;
7+
8+
class BulkWriteFunctionalTest extends FunctionalTestCase
9+
{
10+
private $omitModifiedCount;
11+
12+
public function setUp()
13+
{
14+
parent::setUp();
15+
16+
$this->omitModifiedCount = version_compare($this->getServerVersion(), '2.6.0', '<');
17+
}
18+
19+
public function testInserts()
20+
{
21+
$ops = array(
22+
array('insertOne' => array(array('_id' => 1, 'x' => 11))),
23+
array('insertOne' => array(array('x' => 22))),
24+
);
25+
26+
$result = $this->collection->bulkWrite($ops);
27+
$this->assertSame(2, $result->getInsertedCount());
28+
29+
$insertedIds = $result->getInsertedIds();
30+
$this->assertSame(1, $insertedIds[0]);
31+
$this->assertInstanceOf('BSON\ObjectId', $insertedIds[1]);
32+
33+
$expected = array(
34+
array('_id' => $insertedIds[0], 'x' => 11),
35+
array('_id' => $insertedIds[1], 'x' => 22),
36+
);
37+
38+
$this->assertEquals($expected, $this->collection->find()->toArray());
39+
}
40+
41+
public function testUpdates()
42+
{
43+
$this->createFixtures(4);
44+
45+
$ops = array(
46+
array('updateOne' => array(array('_id' => 2), array('$inc' => array('x' => 1)))),
47+
array('updateMany' => array(array('_id' => array('$gt' => 2)), array('$inc' => array('x' => -1)))),
48+
array('updateOne' => array(array('_id' => 5), array('$set' => array('x' => 55)), array('upsert' => true))),
49+
array('updateOne' => array(array('x' => 66), array('$set' => array('x' => 66)), array('upsert' => true))),
50+
array('updateMany' => array(array('x' => array('$gt' => 50)), array('$inc' => array('x' => 1)))),
51+
);
52+
53+
$result = $this->collection->bulkWrite($ops);
54+
$this->assertSame(5, $result->getMatchedCount());
55+
$this->omitModifiedCount or $this->assertSame(5, $result->getModifiedCount());
56+
$this->assertSame(2, $result->getUpsertedCount());
57+
58+
$upsertedIds = $result->getUpsertedIds();
59+
$this->assertSame(5, $upsertedIds[2]);
60+
$this->assertInstanceOf('BSON\ObjectId', $upsertedIds[3]);
61+
62+
$expected = array(
63+
array('_id' => 1, 'x' => 11),
64+
array('_id' => 2, 'x' => 23),
65+
array('_id' => 3, 'x' => 32),
66+
array('_id' => 4, 'x' => 43),
67+
array('_id' => 5, 'x' => 56),
68+
array('_id' => $upsertedIds[3], 'x' => 67),
69+
);
70+
71+
$this->assertEquals($expected, $this->collection->find()->toArray());
72+
}
73+
74+
public function testDeletes()
75+
{
76+
$this->createFixtures(4);
77+
78+
$ops = array(
79+
array('deleteOne' => array(array('_id' => 1))),
80+
array('deleteMany' => array(array('_id' => array('$gt' => 2)))),
81+
);
82+
83+
$result = $this->collection->bulkWrite($ops);
84+
$this->assertSame(3, $result->getDeletedCount());
85+
86+
$expected = array(
87+
array('_id' => 2, 'x' => 22),
88+
);
89+
90+
$this->assertEquals($expected, $this->collection->find()->toArray());
91+
}
92+
93+
/**
94+
* Create data fixtures.
95+
*
96+
* @param integer $n
97+
*/
98+
private function createFixtures($n)
99+
{
100+
$bulkWrite = new BulkWrite(true);
101+
102+
for ($i = 1; $i <= $n; $i++) {
103+
$bulkWrite->insert(array(
104+
'_id' => $i,
105+
'x' => (integer) ($i . $i),
106+
));
107+
}
108+
109+
$result = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite);
110+
111+
$this->assertEquals($n, $result->getInsertedCount());
112+
}
113+
}

0 commit comments

Comments
 (0)