Skip to content

Commit bc3529a

Browse files
committed
PHPORM-103 Use Aggregation Builder for the query builder
1 parent a05bd53 commit bc3529a

File tree

4 files changed

+80
-55
lines changed

4 files changed

+80
-55
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"mongodb/mongodb": "^1.15"
3232
},
3333
"require-dev": {
34+
"mongodb/builder": "^0.1",
3435
"phpunit/phpunit": "^10.3",
3536
"orchestra/testbench": "^8.0|^9.0",
3637
"mockery/mockery": "^1.4.4",

src/Query/Builder.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,17 @@
2121
use MongoDB\BSON\ObjectID;
2222
use MongoDB\BSON\Regex;
2323
use MongoDB\BSON\UTCDateTime;
24+
use MongoDB\Builder\Accumulator\FirstAccumulator;
25+
use MongoDB\Builder\BuilderEncoder;
26+
use MongoDB\Builder\Expression\FieldPath;
27+
use MongoDB\Builder\Pipeline;
28+
use MongoDB\Builder\Stage\GroupStage;
29+
use MongoDB\Builder\Stage\LimitStage;
30+
use MongoDB\Builder\Stage\MatchStage;
31+
use MongoDB\Builder\Stage\ReplaceRootStage;
32+
use MongoDB\Builder\Stage\SkipStage;
33+
use MongoDB\Builder\Stage\SortStage;
34+
use MongoDB\Builder\Variable;
2435
use MongoDB\Driver\Cursor;
2536
use Override;
2637
use RuntimeException;
@@ -297,6 +308,8 @@ public function toMql(): array
297308

298309
$wheres = $this->compileWheres();
299310

311+
$pipeline = [new MatchStage($wheres)];
312+
300313
// Use MongoDB's aggregation framework when using grouping or aggregation functions.
301314
if ($this->groups || $this->aggregate) {
302315
$group = [];
@@ -409,7 +422,13 @@ public function toMql(): array
409422

410423
$options = $this->inheritConnectionOptions();
411424

412-
return ['distinct' => [$column, $wheres, $options]];
425+
$pipeline[] = new GroupStage(
426+
_id: new FieldPath($column),
427+
_document: new FirstAccumulator(Variable::root()),
428+
);
429+
$pipeline[] = new ReplaceRootStage(
430+
newRoot: new FieldPath('_document'),
431+
);
413432
}
414433

415434
// Normal query
@@ -429,18 +448,19 @@ public function toMql(): array
429448
}
430449

431450
if ($this->orders) {
432-
$options['sort'] = $this->orders;
451+
$pipeline[] = new SortStage($this->orders);
433452
}
434453

435454
if ($this->offset) {
436-
$options['skip'] = $this->offset;
455+
$pipeline[] = new SkipStage($this->offset);
437456
}
438457

439458
if ($this->limit) {
440-
$options['limit'] = $this->limit;
459+
$pipeline[] = new LimitStage($this->limit);
441460
}
442461

443462
if ($this->hint) {
463+
// @todo
444464
$options['hint'] = $this->hint;
445465
}
446466

@@ -458,7 +478,10 @@ public function toMql(): array
458478

459479
$options = $this->inheritConnectionOptions($options);
460480

461-
return ['find' => [$wheres, $options]];
481+
$encoder = new BuilderEncoder();
482+
$pipeline = $encoder->encode(new Pipeline(...$pipeline));
483+
484+
return ['aggregate' => [$pipeline, $options]];
462485
}
463486

464487
/**

tests/ModelTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,6 +1006,7 @@ public function testNumericFieldName(): void
10061006
$user->{2} = ['3' => 'two.three'];
10071007
$user->save();
10081008

1009+
// Test failure: 1 is transformed into 0 by array unpacking and variadic arguments
10091010
$found = User::where(1, 'one')->first();
10101011
$this->assertInstanceOf(User::class, $found);
10111012
$this->assertEquals('one', $found[1]);

0 commit comments

Comments
 (0)