2
2
3
3
namespace MongoDB \Tests \Operation ;
4
4
5
+ use MongoDB \BSON \Document ;
5
6
use MongoDB \BSON \ObjectId ;
7
+ use MongoDB \BSON \PackedArray ;
6
8
use MongoDB \BulkWriteResult ;
7
9
use MongoDB \Collection ;
8
10
use MongoDB \Driver \BulkWrite as Bulk ;
9
11
use MongoDB \Driver \WriteConcern ;
10
12
use MongoDB \Exception \BadMethodCallException ;
13
+ use MongoDB \Model \BSONArray ;
11
14
use MongoDB \Model \BSONDocument ;
12
15
use MongoDB \Operation \BulkWrite ;
13
16
use MongoDB \Tests \CommandObserver ;
17
+ use stdClass ;
14
18
19
+ use function is_array ;
15
20
use function version_compare ;
16
21
17
22
class BulkWriteFunctionalTest extends FunctionalTestCase
@@ -57,6 +62,60 @@ public function testInserts(): void
57
62
$ this ->assertSameDocuments ($ expected , $ this ->collection ->find ());
58
63
}
59
64
65
+ /**
66
+ * @dataProvider provideDocumentsWithIds
67
+ * @dataProvider provideDocumentsWithoutIds
68
+ */
69
+ public function testInsertDocumentEncoding ($ document , stdClass $ expectedDocument ): void
70
+ {
71
+ (new CommandObserver ())->observe (
72
+ function () use ($ document , $ expectedDocument ): void {
73
+ $ operation = new BulkWrite (
74
+ $ this ->getDatabaseName (),
75
+ $ this ->getCollectionName (),
76
+ [['insertOne ' => [$ document ]]]
77
+ );
78
+
79
+ $ result = $ operation ->execute ($ this ->getPrimaryServer ());
80
+
81
+ // Replace _id placeholder if necessary
82
+ if ($ expectedDocument ->_id === null ) {
83
+ $ expectedDocument ->_id = $ result ->getInsertedIds ()[0 ];
84
+ }
85
+ },
86
+ function (array $ event ) use ($ expectedDocument ): void {
87
+ $ this ->assertEquals ($ expectedDocument , $ event ['started ' ]->getCommand ()->documents [0 ] ?? null );
88
+ }
89
+ );
90
+ }
91
+
92
+ public function provideDocumentsWithIds (): array
93
+ {
94
+ $ expectedDocument = (object ) ['_id ' => 1 ];
95
+
96
+ return [
97
+ 'with_id:array ' => [['_id ' => 1 ], $ expectedDocument ],
98
+ 'with_id:object ' => [(object ) ['_id ' => 1 ], $ expectedDocument ],
99
+ 'with_id:Serializable ' => [new BSONDocument (['_id ' => 1 ]), $ expectedDocument ],
100
+ 'with_id:Document ' => [Document::fromPHP (['_id ' => 1 ]), $ expectedDocument ],
101
+ ];
102
+ }
103
+
104
+ public function provideDocumentsWithoutIds (): array
105
+ {
106
+ /* Note: _id placeholders must be replaced with generated ObjectIds. We
107
+ * also clone the value for each data set since tests may need to modify
108
+ * the object. */
109
+ $ expectedDocument = (object ) ['_id ' => null , 'x ' => 1 ];
110
+
111
+ return [
112
+ 'without_id:array ' => [['x ' => 1 ], clone $ expectedDocument ],
113
+ 'without_id:object ' => [(object ) ['x ' => 1 ], clone $ expectedDocument ],
114
+ 'without_id:Serializable ' => [new BSONDocument (['x ' => 1 ]), clone $ expectedDocument ],
115
+ 'without_id:Document ' => [Document::fromPHP (['x ' => 1 ]), clone $ expectedDocument ],
116
+ ];
117
+ }
118
+
60
119
public function testUpdates (): void
61
120
{
62
121
$ this ->createFixtures (4 );
@@ -93,6 +152,127 @@ public function testUpdates(): void
93
152
$ this ->assertSameDocuments ($ expected , $ this ->collection ->find ());
94
153
}
95
154
155
+ /** @dataProvider provideFilterDocuments */
156
+ public function testUpdateFilterDocuments ($ filter , stdClass $ expectedFilter ): void
157
+ {
158
+ (new CommandObserver ())->observe (
159
+ function () use ($ filter ): void {
160
+ $ operation = new BulkWrite (
161
+ $ this ->getDatabaseName (),
162
+ $ this ->getCollectionName (),
163
+ [
164
+ ['replaceOne ' => [$ filter , ['x ' => 1 ]]],
165
+ ['updateOne ' => [$ filter , ['$set ' => ['x ' => 1 ]]]],
166
+ ['updateMany ' => [$ filter , ['$set ' => ['x ' => 1 ]]]],
167
+ ]
168
+ );
169
+
170
+ $ operation ->execute ($ this ->getPrimaryServer ());
171
+ },
172
+ function (array $ event ) use ($ expectedFilter ): void {
173
+ $ this ->assertEquals ($ expectedFilter , $ event ['started ' ]->getCommand ()->updates [0 ]->q ?? null );
174
+ $ this ->assertEquals ($ expectedFilter , $ event ['started ' ]->getCommand ()->updates [1 ]->q ?? null );
175
+ $ this ->assertEquals ($ expectedFilter , $ event ['started ' ]->getCommand ()->updates [2 ]->q ?? null );
176
+ }
177
+ );
178
+ }
179
+
180
+ public function provideFilterDocuments (): array
181
+ {
182
+ $ expectedQuery = (object ) ['x ' => 1 ];
183
+
184
+ return [
185
+ 'array ' => [['x ' => 1 ], $ expectedQuery ],
186
+ 'object ' => [(object ) ['x ' => 1 ], $ expectedQuery ],
187
+ 'Serializable ' => [new BSONDocument (['x ' => 1 ]), $ expectedQuery ],
188
+ 'Document ' => [Document::fromPHP (['x ' => 1 ]), $ expectedQuery ],
189
+ ];
190
+ }
191
+
192
+ /** @dataProvider provideReplacementDocuments */
193
+ public function testReplacementDocuments ($ replacement , stdClass $ expectedReplacement ): void
194
+ {
195
+ (new CommandObserver ())->observe (
196
+ function () use ($ replacement ): void {
197
+ $ operation = new BulkWrite (
198
+ $ this ->getDatabaseName (),
199
+ $ this ->getCollectionName (),
200
+ [['replaceOne ' => [['x ' => 1 ], $ replacement ]]]
201
+ );
202
+
203
+ $ operation ->execute ($ this ->getPrimaryServer ());
204
+ },
205
+ function (array $ event ) use ($ expectedReplacement ): void {
206
+ $ this ->assertEquals ($ expectedReplacement , $ event ['started ' ]->getCommand ()->updates [0 ]->u ?? null );
207
+ }
208
+ );
209
+ }
210
+
211
+ public function provideReplacementDocuments (): array
212
+ {
213
+ $ expected = (object ) ['x ' => 1 ];
214
+
215
+ return [
216
+ 'replacement:array ' => [['x ' => 1 ], $ expected ],
217
+ 'replacement:object ' => [(object ) ['x ' => 1 ], $ expected ],
218
+ 'replacement:Serializable ' => [new BSONDocument (['x ' => 1 ]), $ expected ],
219
+ 'replacement:Document ' => [Document::fromPHP (['x ' => 1 ]), $ expected ],
220
+ ];
221
+ }
222
+
223
+ /**
224
+ * @dataProvider provideUpdateDocuments
225
+ * @dataProvider provideUpdatePipelines
226
+ */
227
+ public function testUpdateDocuments ($ update , $ expectedUpdate ): void
228
+ {
229
+ if (is_array ($ expectedUpdate ) && version_compare ($ this ->getServerVersion (), '4.2.0 ' , '< ' )) {
230
+ $ this ->markTestSkipped ('Pipeline-style updates are not supported ' );
231
+ }
232
+
233
+ (new CommandObserver ())->observe (
234
+ function () use ($ update ): void {
235
+ $ operation = new BulkWrite (
236
+ $ this ->getDatabaseName (),
237
+ $ this ->getCollectionName (),
238
+ [
239
+ ['updateOne ' => [['x ' => 1 ], $ update ]],
240
+ ['updateMany ' => [['x ' => 1 ], $ update ]],
241
+ ]
242
+ );
243
+
244
+ $ operation ->execute ($ this ->getPrimaryServer ());
245
+ },
246
+ function (array $ event ) use ($ expectedUpdate ): void {
247
+ $ this ->assertEquals ($ expectedUpdate , $ event ['started ' ]->getCommand ()->updates [0 ]->u ?? null );
248
+ $ this ->assertEquals ($ expectedUpdate , $ event ['started ' ]->getCommand ()->updates [1 ]->u ?? null );
249
+ }
250
+ );
251
+ }
252
+
253
+ public function provideUpdateDocuments (): array
254
+ {
255
+ $ expected = (object ) ['$set ' => (object ) ['x ' => 1 ]];
256
+
257
+ return [
258
+ 'update:array ' => [['$set ' => ['x ' => 1 ]], $ expected ],
259
+ 'update:object ' => [(object ) ['$set ' => ['x ' => 1 ]], $ expected ],
260
+ 'update:Serializable ' => [new BSONDocument (['$set ' => ['x ' => 1 ]]), $ expected ],
261
+ 'update:Document ' => [Document::fromPHP (['$set ' => ['x ' => 1 ]]), $ expected ],
262
+ ];
263
+ }
264
+
265
+ public function provideUpdatePipelines (): array
266
+ {
267
+ $ expected = [(object ) ['$set ' => (object ) ['x ' => 1 ]]];
268
+
269
+ return [
270
+ 'pipeline:array ' => [[['$set ' => ['x ' => 1 ]]], $ expected ],
271
+ 'pipeline:Serializable ' => [new BSONArray ([['$set ' => ['x ' => 1 ]]]), $ expected ],
272
+ 'pipeline:PackedArray ' => [PackedArray::fromPHP ([['$set ' => ['x ' => 1 ]]]), $ expected ],
273
+ ];
274
+ }
275
+
96
276
public function testDeletes (): void
97
277
{
98
278
$ this ->createFixtures (4 );
@@ -115,6 +295,29 @@ public function testDeletes(): void
115
295
$ this ->assertSameDocuments ($ expected , $ this ->collection ->find ());
116
296
}
117
297
298
+ /** @dataProvider provideFilterDocuments */
299
+ public function testDeleteFilterDocuments ($ filter , stdClass $ expectedQuery ): void
300
+ {
301
+ (new CommandObserver ())->observe (
302
+ function () use ($ filter ): void {
303
+ $ operation = new BulkWrite (
304
+ $ this ->getDatabaseName (),
305
+ $ this ->getCollectionName (),
306
+ [
307
+ ['deleteOne ' => [$ filter ]],
308
+ ['deleteMany ' => [$ filter ]],
309
+ ]
310
+ );
311
+
312
+ $ operation ->execute ($ this ->getPrimaryServer ());
313
+ },
314
+ function (array $ event ) use ($ expectedQuery ): void {
315
+ $ this ->assertEquals ($ expectedQuery , $ event ['started ' ]->getCommand ()->deletes [0 ]->q ?? null );
316
+ $ this ->assertEquals ($ expectedQuery , $ event ['started ' ]->getCommand ()->deletes [1 ]->q ?? null );
317
+ }
318
+ );
319
+ }
320
+
118
321
public function testMixedOrderedOperations (): void
119
322
{
120
323
$ this ->createFixtures (3 );
0 commit comments