Skip to content

Commit 9703f09

Browse files
committed
Rework built-in aggregations using aggregation builder
1 parent e4ea7b3 commit 9703f09

File tree

2 files changed

+27
-22
lines changed

2 files changed

+27
-22
lines changed

src/Query/Builder.php

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
use MongoDB\Builder\BuilderEncoder;
2626
use MongoDB\Builder\Expression\FieldPath;
2727
use MongoDB\Builder\Pipeline;
28+
use MongoDB\Builder\Stage;
29+
use MongoDB\Builder\Stage\CountStage;
2830
use MongoDB\Builder\Stage\GroupStage;
2931
use MongoDB\Builder\Stage\LimitStage;
3032
use MongoDB\Builder\Stage\MatchStage;
@@ -303,9 +305,12 @@ protected function getPipeline(): array
303305
$columns = [];
304306
}
305307

308+
$pipeline = [];
306309
$wheres = $this->compileWheres();
307310

308-
$pipeline = [new MatchStage($wheres)];
311+
if (count($wheres)) {
312+
$pipeline[] = new MatchStage($wheres);
313+
}
309314

310315
// Use MongoDB's aggregation framework when using grouping or aggregation functions.
311316
if ($this->groups || $this->aggregate) {
@@ -369,7 +374,7 @@ protected function getPipeline(): array
369374
// Build the aggregation pipeline.
370375
$pipeline = [];
371376
if ($wheres) {
372-
$pipeline[] = new MatchStage(...$wheres);
377+
$pipeline[] = Stage::match(...$wheres);
373378
}
374379

375380
// apply unwinds for subdocument array aggregation
@@ -398,27 +403,14 @@ protected function getPipeline(): array
398403
$pipeline[] = new ProjectStage(...$this->projections);
399404
}
400405

401-
$options = [
402-
'typeMap' => ['root' => 'array', 'document' => 'array'],
403-
];
404-
405-
// Add custom query options
406-
if (count($this->options)) {
407-
$options = array_merge($options, $this->options);
408-
}
409-
410-
$options = $this->inheritConnectionOptions($options);
411-
412-
return ['aggregate' => [$pipeline, $options]];
406+
return $pipeline;
413407
}
414408

415409
// Distinct query
416410
if ($this->distinct) {
417411
// Return distinct results directly
418412
$column = $columns[0] ?? '_id';
419413

420-
$options = $this->inheritConnectionOptions();
421-
422414
$pipeline[] = new GroupStage(
423415
_id: new FieldPath($column),
424416
_document: new FirstAccumulator(Variable::root()),
@@ -562,10 +554,7 @@ public function generateCacheKey()
562554
return md5(serialize(array_values($key)));
563555
}
564556

565-
/**
566-
* @return self|PipelineBuilder
567-
* @psalm-return $function === null ? PipelineBuilder : self
568-
*/
557+
/** @return ($function === null ? PipelineBuilder : self) */
569558
public function aggregate($function = null, $columns = [])
570559
{
571560
if ($function === null) {
@@ -602,6 +591,19 @@ public function aggregate($function = null, $columns = [])
602591
}
603592
}
604593

594+
public function count($columns = '*'): int
595+
{
596+
if ($columns !== '*') {
597+
// @todo trigger warning, $columns is ignored
598+
}
599+
600+
return $this
601+
->aggregate()
602+
->count('aggregate')
603+
->get()
604+
->value('aggregate', 0);
605+
}
606+
605607
/** @inheritdoc */
606608
public function exists()
607609
{
@@ -980,7 +982,7 @@ public function runPaginationCountQuery($columns = ['*'])
980982
->toMql();
981983

982984
// Adds the $count stage to the pipeline
983-
$mql['aggregate'][0][] = ['$count' => 'aggregate'];
985+
$mql['aggregate'][0][] = new CountStage('aggregate');
984986

985987
return $this->collection->aggregate($mql['aggregate'][0], $mql['aggregate'][1])->toArray();
986988
}

tests/QueryBuilderTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use MongoDB\BSON\ObjectId;
1616
use MongoDB\BSON\Regex;
1717
use MongoDB\BSON\UTCDateTime;
18+
use MongoDB\Builder\Expression;
1819
use MongoDB\Driver\Cursor;
1920
use MongoDB\Driver\Monitoring\CommandFailedEvent;
2021
use MongoDB\Driver\Monitoring\CommandStartedEvent;
@@ -848,7 +849,9 @@ public function testProjections()
848849
['name' => 'spoon', 'tags' => ['round', 'bowl']],
849850
]);
850851

851-
$results = DB::collection('items')->project(['tags' => ['$slice' => 1]])->get();
852+
$results = DB::collection('items')
853+
->project(['tags' => Expression::slice(Expression::arrayFieldPath('tags'), 1)])
854+
->get();
852855

853856
foreach ($results as $result) {
854857
$this->assertEquals(1, count($result['tags']));

0 commit comments

Comments
 (0)