1515use MongoDB \BSON \ObjectID ;
1616use MongoDB \BSON \Regex ;
1717use MongoDB \BSON \UTCDateTime ;
18+ use MongoDB \Driver \Cursor ;
1819use RuntimeException ;
1920
2021/**
@@ -215,27 +216,21 @@ public function cursor($columns = [])
215216 }
216217
217218 /**
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]] .
219220 *
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[]>
223224 */
224- public function getFresh ( $ columns = [], $ returnLazy = false )
225+ public function toMql (): array
225226 {
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 ?? [];
232228
233229 // 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 = [];
236232 }
237233
238- // Compile wheres
239234 $ wheres = $ this ->compileWheres ();
240235
241236 // Use MongoDB's aggregation framework when using grouping or aggregation functions.
@@ -254,7 +249,7 @@ public function getFresh($columns = [], $returnLazy = false)
254249 }
255250
256251 // Do the same for other columns that are selected.
257- foreach ($ this -> columns as $ column ) {
252+ foreach ($ columns as $ column ) {
258253 $ key = str_replace ('. ' , '_ ' , $ column );
259254
260255 $ group [$ key ] = ['$last ' => '$ ' .$ column ];
@@ -274,26 +269,10 @@ public function getFresh($columns = [], $returnLazy = false)
274269 $ column = implode ('. ' , $ splitColumns );
275270 }
276271
277- // Null coalense only > 7.2
278-
279272 $ aggregations = blank ($ this ->aggregate ['columns ' ]) ? [] : $ this ->aggregate ['columns ' ];
280273
281274 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 , []]];
297276 } elseif ($ function == 'count ' ) {
298277 // Translate count into sum.
299278 $ group ['aggregate ' ] = ['$sum ' => 1 ];
@@ -348,34 +327,23 @@ public function getFresh($columns = [], $returnLazy = false)
348327
349328 $ options = $ this ->inheritConnectionOptions ($ options );
350329
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 ]];
356331 } // Distinct query
357332 elseif ($ this ->distinct ) {
358333 // Return distinct results directly
359- $ column = isset ($ this -> columns [0 ]) ? $ this -> columns [0 ] : '_id ' ;
334+ $ column = isset ($ columns [0 ]) ? $ columns [0 ] : '_id ' ;
360335
361336 $ options = $ this ->inheritConnectionOptions ();
362337
363- // Execute distinct
364- $ result = $ this ->collection ->distinct ($ column , $ wheres ?: [], $ options );
365-
366- return new Collection ($ result );
338+ return ['distinct ' => [$ column , $ wheres ?: [], $ options ]];
367339 } // Normal query
368340 else {
369- $ columns = [];
370-
371341 // Convert select columns to simple projections.
372- foreach ($ this ->columns as $ column ) {
373- $ columns [$ column ] = true ;
374- }
342+ $ projection = array_fill_keys ($ columns , true );
375343
376344 // Add custom projections.
377345 if ($ this ->projections ) {
378- $ columns = array_merge ($ columns , $ this ->projections );
346+ $ projection = array_merge ($ projection , $ this ->projections );
379347 }
380348 $ options = [];
381349
@@ -395,8 +363,8 @@ public function getFresh($columns = [], $returnLazy = false)
395363 if ($ this ->hint ) {
396364 $ options ['hint ' ] = $ this ->hint ;
397365 }
398- if ($ columns ) {
399- $ options ['projection ' ] = $ columns ;
366+ if ($ projection ) {
367+ $ options ['projection ' ] = $ projection ;
400368 }
401369
402370 // Fix for legacy support, converts the results to arrays instead of objects.
@@ -409,22 +377,62 @@ public function getFresh($columns = [], $returnLazy = false)
409377
410378 $ options = $ this ->inheritConnectionOptions ($ options );
411379
412- // Execute query and get MongoCursor
413- $ cursor = $ this ->collection ->find ($ wheres , $ options );
380+ return ['find ' => [$ wheres , $ options ]];
381+ }
382+ }
414383
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+ }
422422
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+ }
425430
426- return new Collection ($ results );
431+ if ($ result instanceof Cursor) {
432+ $ result = $ result ->toArray ();
427433 }
434+
435+ return new Collection ($ result );
428436 }
429437
430438 /**
0 commit comments