Skip to content

Commit 1eda4de

Browse files
authored
PHPORM-106 Implement pagination for groupBy queries (#2672)
1 parent 899a235 commit 1eda4de

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

src/Query/Builder.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,28 @@ public function newQuery()
910910
return new static($this->connection, $this->grammar, $this->processor);
911911
}
912912

913+
public function runPaginationCountQuery($columns = ['*'])
914+
{
915+
if ($this->distinct) {
916+
throw new BadMethodCallException('Distinct queries cannot be used for pagination. Use GroupBy instead');
917+
}
918+
919+
if ($this->groups || $this->havings) {
920+
$without = $this->unions ? ['orders', 'limit', 'offset'] : ['columns', 'orders', 'limit', 'offset'];
921+
922+
$mql = $this->cloneWithout($without)
923+
->cloneWithoutBindings($this->unions ? ['order'] : ['select', 'order'])
924+
->toMql();
925+
926+
// Adds the $count stage to the pipeline
927+
$mql['aggregate'][0][] = ['$count' => 'aggregate'];
928+
929+
return $this->collection->aggregate($mql['aggregate'][0], $mql['aggregate'][1])->toArray();
930+
}
931+
932+
return parent::runPaginationCountQuery($columns);
933+
}
934+
913935
/**
914936
* Perform an update query.
915937
*

tests/QueryTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace MongoDB\Laravel\Tests;
66

7+
use BadMethodCallException;
78
use DateTimeImmutable;
89
use LogicException;
910
use MongoDB\BSON\Regex;
@@ -534,6 +535,44 @@ public function testCursorPaginate(): void
534535
$this->assertNull($results->first()->title);
535536
}
536537

538+
public function testPaginateGroup(): void
539+
{
540+
// First page
541+
$results = User::groupBy('age')->paginate(2);
542+
$this->assertEquals(2, $results->count());
543+
$this->assertEquals(6, $results->total());
544+
$this->assertEquals(3, $results->lastPage());
545+
$this->assertEquals(1, $results->currentPage());
546+
$this->assertCount(2, $results->items());
547+
$this->assertArrayHasKey('age', $results->first()->getAttributes());
548+
549+
// Last page has fewer results
550+
$results = User::groupBy('age')->paginate(4, page: 2);
551+
$this->assertEquals(2, $results->count());
552+
$this->assertEquals(6, $results->total());
553+
$this->assertEquals(2, $results->lastPage());
554+
$this->assertEquals(2, $results->currentPage());
555+
$this->assertCount(2, $results->items());
556+
$this->assertArrayHasKey('age', $results->first()->getAttributes());
557+
558+
// Using a filter
559+
$results = User::where('title', 'admin')->groupBy('age')->paginate(4);
560+
$this->assertEquals(2, $results->count());
561+
$this->assertEquals(2, $results->total());
562+
$this->assertEquals(1, $results->lastPage());
563+
$this->assertEquals(1, $results->currentPage());
564+
$this->assertCount(2, $results->items());
565+
$this->assertArrayHasKey('age', $results->last()->getAttributes());
566+
}
567+
568+
public function testPaginateDistinct(): void
569+
{
570+
$this->expectException(BadMethodCallException::class);
571+
$this->expectExceptionMessage('Distinct queries cannot be used for pagination. Use GroupBy instead');
572+
573+
User::distinct('age')->paginate(2);
574+
}
575+
537576
public function testUpdate(): void
538577
{
539578
$this->assertEquals(1, User::where(['name' => 'John Doe'])->update(['name' => 'Jim Morrison']));

0 commit comments

Comments
 (0)