15
15
use MongoDB \BSON \ObjectID ;
16
16
use MongoDB \BSON \Regex ;
17
17
use MongoDB \BSON \UTCDateTime ;
18
+ use MongoDB \Driver \Cursor ;
18
19
use RuntimeException ;
19
20
20
21
/**
@@ -215,27 +216,21 @@ public function cursor($columns = [])
215
216
}
216
217
217
218
/**
218
- * Execute the query as a fresh "select" statement .
219
+ * Return the MongoDB query to be run in the form of an element array like ['method' => [arguments]] .
219
220
*
220
- * @param array $columns
221
- * @param bool $returnLazy
222
- * @return array|static[]|Collection|LazyCollection
221
+ * Example: ['find' => [['name' => 'John Doe'], ['projection' => ['birthday' => 1]]]]
222
+ *
223
+ * @return array<string, mixed[]>
223
224
*/
224
- public function getFresh ( $ columns = [], $ returnLazy = false )
225
+ public function toMql (): array
225
226
{
226
- // If no columns have been specified for the select statement, we will set them
227
- // here to either the passed columns, or the standard default of retrieving
228
- // all of the columns on the table using the "wildcard" column character.
229
- if ($ this ->columns === null ) {
230
- $ this ->columns = $ columns ;
231
- }
227
+ $ columns = $ this ->columns ?? [];
232
228
233
229
// Drop all columns if * is present, MongoDB does not work this way.
234
- if (in_array ('* ' , $ this -> columns )) {
235
- $ this -> columns = [];
230
+ if (in_array ('* ' , $ columns )) {
231
+ $ columns = [];
236
232
}
237
233
238
- // Compile wheres
239
234
$ wheres = $ this ->compileWheres ();
240
235
241
236
// Use MongoDB's aggregation framework when using grouping or aggregation functions.
@@ -254,7 +249,7 @@ public function getFresh($columns = [], $returnLazy = false)
254
249
}
255
250
256
251
// Do the same for other columns that are selected.
257
- foreach ($ this -> columns as $ column ) {
252
+ foreach ($ columns as $ column ) {
258
253
$ key = str_replace ('. ' , '_ ' , $ column );
259
254
260
255
$ group [$ key ] = ['$last ' => '$ ' .$ column ];
@@ -274,26 +269,10 @@ public function getFresh($columns = [], $returnLazy = false)
274
269
$ column = implode ('. ' , $ splitColumns );
275
270
}
276
271
277
- // Null coalense only > 7.2
278
-
279
272
$ aggregations = blank ($ this ->aggregate ['columns ' ]) ? [] : $ this ->aggregate ['columns ' ];
280
273
281
274
if (in_array ('* ' , $ aggregations ) && $ function == 'count ' ) {
282
- // When ORM is paginating, count doesnt need a aggregation, just a cursor operation
283
- // elseif added to use this only in pagination
284
- // https://docs.mongodb.com/manual/reference/method/cursor.count/
285
- // count method returns int
286
-
287
- $ totalResults = $ this ->collection ->count ($ wheres );
288
- // Preserving format expected by framework
289
- $ results = [
290
- [
291
- '_id ' => null ,
292
- 'aggregate ' => $ totalResults ,
293
- ],
294
- ];
295
-
296
- return new Collection ($ results );
275
+ return ['count ' => [$ wheres , []]];
297
276
} elseif ($ function == 'count ' ) {
298
277
// Translate count into sum.
299
278
$ group ['aggregate ' ] = ['$sum ' => 1 ];
@@ -348,34 +327,23 @@ public function getFresh($columns = [], $returnLazy = false)
348
327
349
328
$ options = $ this ->inheritConnectionOptions ($ options );
350
329
351
- // Execute aggregation
352
- $ results = iterator_to_array ($ this ->collection ->aggregate ($ pipeline , $ options ));
353
-
354
- // Return results
355
- return new Collection ($ results );
330
+ return ['aggregate ' => [$ pipeline , $ options ]];
356
331
} // Distinct query
357
332
elseif ($ this ->distinct ) {
358
333
// Return distinct results directly
359
- $ column = isset ($ this -> columns [0 ]) ? $ this -> columns [0 ] : '_id ' ;
334
+ $ column = isset ($ columns [0 ]) ? $ columns [0 ] : '_id ' ;
360
335
361
336
$ options = $ this ->inheritConnectionOptions ();
362
337
363
- // Execute distinct
364
- $ result = $ this ->collection ->distinct ($ column , $ wheres ?: [], $ options );
365
-
366
- return new Collection ($ result );
338
+ return ['distinct ' => [$ column , $ wheres ?: [], $ options ]];
367
339
} // Normal query
368
340
else {
369
- $ columns = [];
370
-
371
341
// Convert select columns to simple projections.
372
- foreach ($ this ->columns as $ column ) {
373
- $ columns [$ column ] = true ;
374
- }
342
+ $ projection = array_fill_keys ($ columns , true );
375
343
376
344
// Add custom projections.
377
345
if ($ this ->projections ) {
378
- $ columns = array_merge ($ columns , $ this ->projections );
346
+ $ projection = array_merge ($ projection , $ this ->projections );
379
347
}
380
348
$ options = [];
381
349
@@ -395,8 +363,8 @@ public function getFresh($columns = [], $returnLazy = false)
395
363
if ($ this ->hint ) {
396
364
$ options ['hint ' ] = $ this ->hint ;
397
365
}
398
- if ($ columns ) {
399
- $ options ['projection ' ] = $ columns ;
366
+ if ($ projection ) {
367
+ $ options ['projection ' ] = $ projection ;
400
368
}
401
369
402
370
// Fix for legacy support, converts the results to arrays instead of objects.
@@ -409,22 +377,62 @@ public function getFresh($columns = [], $returnLazy = false)
409
377
410
378
$ options = $ this ->inheritConnectionOptions ($ options );
411
379
412
- // Execute query and get MongoCursor
413
- $ cursor = $ this ->collection ->find ($ wheres , $ options );
380
+ return ['find ' => [$ wheres , $ options ]];
381
+ }
382
+ }
414
383
415
- if ($ returnLazy ) {
416
- return LazyCollection::make (function () use ($ cursor ) {
417
- foreach ($ cursor as $ item ) {
418
- yield $ item ;
419
- }
420
- });
421
- }
384
+ /**
385
+ * Execute the query as a fresh "select" statement.
386
+ *
387
+ * @param array $columns
388
+ * @param bool $returnLazy
389
+ * @return array|static[]|Collection|LazyCollection
390
+ */
391
+ public function getFresh ($ columns = [], $ returnLazy = false )
392
+ {
393
+ // If no columns have been specified for the select statement, we will set them
394
+ // here to either the passed columns, or the standard default of retrieving
395
+ // all of the columns on the table using the "wildcard" column character.
396
+ if ($ this ->columns === null ) {
397
+ $ this ->columns = $ columns ;
398
+ }
399
+
400
+ // Drop all columns if * is present, MongoDB does not work this way.
401
+ if (in_array ('* ' , $ this ->columns )) {
402
+ $ this ->columns = [];
403
+ }
404
+
405
+ $ command = $ this ->toMql ($ columns );
406
+ assert (count ($ command ) >= 1 , 'At least one method call is required to execute a query ' );
407
+
408
+ $ result = $ this ->collection ;
409
+ foreach ($ command as $ method => $ arguments ) {
410
+ $ result = call_user_func_array ([$ result , $ method ], $ arguments );
411
+ }
412
+
413
+ // countDocuments method returns int, wrap it to the format expected by the framework
414
+ if (is_int ($ result )) {
415
+ $ result = [
416
+ [
417
+ '_id ' => null ,
418
+ 'aggregate ' => $ result ,
419
+ ],
420
+ ];
421
+ }
422
422
423
- // Return results as an array with numeric keys
424
- $ results = iterator_to_array ($ cursor , false );
423
+ if ($ returnLazy ) {
424
+ return LazyCollection::make (function () use ($ result ) {
425
+ foreach ($ result as $ item ) {
426
+ yield $ item ;
427
+ }
428
+ });
429
+ }
425
430
426
- return new Collection ($ results );
431
+ if ($ result instanceof Cursor) {
432
+ $ result = $ result ->toArray ();
427
433
}
434
+
435
+ return new Collection ($ result );
428
436
}
429
437
430
438
/**
0 commit comments