Skip to content

Commit be82295

Browse files
committed
Add agg builder examples
1 parent 2b3c790 commit be82295

File tree

4 files changed

+303
-0
lines changed

4 files changed

+303
-0
lines changed
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\AggregationBlogPost;
4+
5+
use MongoDB\Builder\Accumulator;
6+
use MongoDB\Builder\Expression;
7+
use MongoDB\Builder\Pipeline;
8+
use MongoDB\Builder\Stage;
9+
use MongoDB\Tests\TestCase;
10+
11+
class Example1Test extends TestCase
12+
{
13+
public function testExample1(): void
14+
{
15+
$pipeline = new Pipeline(
16+
Stage::group(
17+
_id: Expression::stringFieldPath('email'),
18+
totalComments: Accumulator::sum(1),
19+
),
20+
Stage::sort(totalComments: -1),
21+
Stage::limit(5),
22+
);
23+
}
24+
}
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\AggregationBlogPost;
4+
5+
use MongoDB\Builder\Accumulator;
6+
use MongoDB\Builder\Expression;
7+
use MongoDB\Builder\Pipeline;
8+
use MongoDB\Builder\Query;
9+
use MongoDB\Builder\Stage;
10+
use MongoDB\Tests\TestCase;
11+
use function MongoDB\object;
12+
13+
class Example2Test extends TestCase
14+
{
15+
public function testExample2(): void
16+
{
17+
$pipeline = new Pipeline(
18+
Stage::match(...[
19+
'imdb.rating' => Query::exists(),
20+
]),
21+
Stage::addFields(
22+
month: Expression::month(Expression::dateFieldPath('released')),
23+
year: Expression::year(Expression::dateFieldPath('released')),
24+
),
25+
Stage::group(
26+
_id: object(
27+
year: Expression::intFieldPath('year'),
28+
month: Expression::intFieldPath('month'),
29+
),
30+
averageRating: Accumulator::avg(Expression::intFieldPath('imdb.rating')),
31+
),
32+
Stage::sort(...[
33+
'_id.year' => 1,
34+
'_id.month' => 1,
35+
]),
36+
);
37+
}
38+
}
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\AggregationBlogPost;
4+
5+
use MongoDB\Builder\Accumulator;
6+
use MongoDB\Builder\Expression;
7+
use MongoDB\Builder\Pipeline;
8+
use MongoDB\Builder\Query;
9+
use MongoDB\Builder\Stage;
10+
use MongoDB\Tests\TestCase;
11+
use function MongoDB\object;
12+
13+
class Example3Test extends TestCase
14+
{
15+
public function testExample3(): void
16+
{
17+
$pipeline = new Pipeline(
18+
Stage::lookup(
19+
as: 'comments',
20+
from: 'comments',
21+
localField: '_id',
22+
foreignField: 'movie_id',
23+
),
24+
Stage::facet(
25+
mostCommentedMovies: new Pipeline(
26+
Stage::project(
27+
_id: 0,
28+
title: 1,
29+
commentCount: Expression::size(Expression::arrayFieldPath('comments')),
30+
),
31+
Stage::sort(commentCount: -1),
32+
Stage::limit(5),
33+
),
34+
mostCommentedGenre: new Pipeline(
35+
Stage::unwind(Expression::arrayFieldPath('genres')),
36+
Stage::group(
37+
_id: expression::stringFieldPath('genres'),
38+
totalComments: Accumulator::sum(Expression::size(Expression::arrayFieldPath('comments'))),
39+
),
40+
Stage::sort(totalComments: -1),
41+
Stage::limit(5),
42+
),
43+
),
44+
);
45+
}
46+
}
+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
<?php
2+
3+
namespace MongoDB\Tests\AggregationBlogPost;
4+
5+
use MongoDB\BSON\Document;
6+
use MongoDB\BSON\Serializable;
7+
use MongoDB\Builder\Accumulator;
8+
use MongoDB\Builder\Expression;
9+
use MongoDB\Builder\Pipeline;
10+
use MongoDB\Builder\Query;
11+
use MongoDB\Builder\Stage;
12+
use MongoDB\Builder\Type\AccumulatorInterface;
13+
use MongoDB\Tests\TestCase;
14+
use stdClass;
15+
use function MongoDB\object;
16+
17+
class Example4Test extends TestCase
18+
{
19+
public function testFirstPipeline(): void
20+
{
21+
$pipeline = new Pipeline(
22+
Stage::lookup(
23+
as: 'movie',
24+
from: 'movies',
25+
localField: 'movie_id',
26+
foreignField: '_id',
27+
),
28+
Stage::unwind(Expression::arrayFieldPath('movie')),
29+
Stage::replaceRoot(object(
30+
comment_id: Expression::objectIdFieldPath('_id'),
31+
user: Expression::stringFieldPath('name'),
32+
movie_id: Expression::objectIdFieldPath('movie_id'),
33+
movie_title: Expression::stringFieldPath('movie.title'),
34+
genres: Expression::arrayFieldPath('movie.genres'),
35+
rating: Expression::intFieldPath('movie.imdb.rating'),
36+
comment: Expression::stringFieldPath('text'),
37+
)),
38+
Stage::unwind(Expression::arrayFieldPath('genres')),
39+
Stage::group(
40+
_id: object(
41+
user: Expression::stringFieldPath('user'),
42+
genre: Expression::stringFieldPath('genres'),
43+
),
44+
totalComments: Accumulator::sum(1),
45+
averageRating: Accumulator::avg(Expression::intFieldPath('rating')),
46+
),
47+
Stage::group(
48+
_id: Expression::stringFieldPath('_id.user'),
49+
preferences: Accumulator::push(object(
50+
genre: Expression::stringFieldPath('_id.genre'),
51+
totalComments: Expression::intFieldPath('totalComments'),
52+
averageRating: Expression::round(Expression::avg(Expression::doubleFieldPath('averageRating')), 2),
53+
)),
54+
totalComments: Accumulator::sum(Expression::intFieldPath('totalComments')),
55+
),
56+
Stage::sort(totalComments: -1),
57+
);
58+
}
59+
60+
public function testExtractLookupStage(): void
61+
{
62+
$pipeline = new Pipeline(
63+
$this->lookupMovie(),
64+
Stage::unwind(Expression::arrayFieldPath('movie')),
65+
Stage::replaceRoot(object(
66+
comment_id: Expression::objectIdFieldPath('_id'),
67+
user: Expression::stringFieldPath('name'),
68+
movie_id: Expression::objectIdFieldPath('movie_id'),
69+
movie_title: Expression::stringFieldPath('movie.title'),
70+
genres: Expression::arrayFieldPath('movie.genres'),
71+
rating: Expression::intFieldPath('movie.imdb.rating'),
72+
comment: Expression::stringFieldPath('text'),
73+
)),
74+
Stage::unwind(Expression::arrayFieldPath('genres')),
75+
Stage::group(
76+
_id: object(
77+
user: Expression::stringFieldPath('user'),
78+
genre: Expression::stringFieldPath('genres'),
79+
),
80+
totalComments: Accumulator::sum(1),
81+
averageRating: Accumulator::avg(Expression::intFieldPath('rating')),
82+
),
83+
Stage::group(
84+
_id: Expression::stringFieldPath('_id.user'),
85+
preferences: Accumulator::push(object(
86+
genre: Expression::stringFieldPath('_id.genre'),
87+
totalComments: Expression::intFieldPath('totalComments'),
88+
averageRating: Expression::round(Expression::avg(Expression::doubleFieldPath('averageRating')), 2),
89+
)),
90+
totalComments: Accumulator::sum(Expression::intFieldPath('totalComments')),
91+
),
92+
Stage::sort(totalComments: -1),
93+
);
94+
}
95+
96+
public function testExtractLookupSingleMovie(): void
97+
{
98+
$pipeline = new Pipeline(
99+
$this->lookupSingleMovie(),
100+
Stage::replaceRoot(object(
101+
comment_id: Expression::objectIdFieldPath('_id'),
102+
user: Expression::stringFieldPath('name'),
103+
movie_id: Expression::objectIdFieldPath('movie_id'),
104+
movie_title: Expression::stringFieldPath('movie.title'),
105+
genres: Expression::arrayFieldPath('movie.genres'),
106+
rating: Expression::intFieldPath('movie.imdb.rating'),
107+
comment: Expression::stringFieldPath('text'),
108+
)),
109+
Stage::unwind(Expression::arrayFieldPath('genres')),
110+
Stage::group(
111+
_id: object(
112+
user: Expression::stringFieldPath('user'),
113+
genre: Expression::stringFieldPath('genres'),
114+
),
115+
totalComments: Accumulator::sum(1),
116+
averageRating: Accumulator::avg(Expression::intFieldPath('rating')),
117+
),
118+
Stage::group(
119+
_id: Expression::stringFieldPath('_id.user'),
120+
preferences: Accumulator::push(object(
121+
genre: Expression::stringFieldPath('_id.genre'),
122+
totalComments: Expression::intFieldPath('totalComments'),
123+
averageRating: Expression::round(Expression::avg(Expression::doubleFieldPath('averageRating')), 2),
124+
)),
125+
totalComments: Accumulator::sum(Expression::intFieldPath('totalComments')),
126+
),
127+
Stage::sort(totalComments: -1),
128+
);
129+
}
130+
131+
public function testExtractGroupByUserAndGenre(): void
132+
{
133+
$pipeline = new Pipeline(
134+
$this->lookupSingleMovie(),
135+
Stage::replaceRoot(object(
136+
comment_id: Expression::objectIdFieldPath('_id'),
137+
user: Expression::stringFieldPath('name'),
138+
movie_id: Expression::objectIdFieldPath('movie_id'),
139+
movie_title: Expression::stringFieldPath('movie.title'),
140+
genres: Expression::arrayFieldPath('movie.genres'),
141+
rating: Expression::intFieldPath('movie.imdb.rating'),
142+
comment: Expression::stringFieldPath('text'),
143+
)),
144+
Stage::unwind(Expression::arrayFieldPath('genres')),
145+
$this->groupByUserAndGenre(
146+
totalComments: Accumulator::sum(1),
147+
averageRating: Accumulator::avg(Expression::intFieldPath('rating')),
148+
),
149+
Stage::group(
150+
_id: Expression::stringFieldPath('_id.user'),
151+
preferences: Accumulator::push(object(
152+
genre: Expression::stringFieldPath('_id.genre'),
153+
totalComments: Expression::intFieldPath('totalComments'),
154+
averageRating: Expression::round(Expression::avg(Expression::doubleFieldPath('averageRating')), 2),
155+
)),
156+
totalComments: Accumulator::sum(Expression::intFieldPath('totalComments')),
157+
),
158+
Stage::sort(totalComments: -1),
159+
);
160+
}
161+
162+
private function lookupMovie(): Stage\LookupStage
163+
{
164+
return Stage::lookup(
165+
as: 'movie',
166+
from: 'movies',
167+
localField: 'movie_id',
168+
foreignField: '_id',
169+
);
170+
}
171+
172+
private function lookupSingleMovie(): Pipeline
173+
{
174+
return new Pipeline(
175+
Stage::lookup(
176+
as: 'movie',
177+
from: 'movies',
178+
localField: 'movie_id',
179+
foreignField: '_id',
180+
),
181+
Stage::unwind(Expression::arrayFieldPath('movie')),
182+
);
183+
}
184+
185+
private function groupByUserAndGenre(Document|Serializable|AccumulatorInterface|stdClass|array ...$field): Stage\GroupStage
186+
{
187+
return Stage::group(
188+
...$field,
189+
_id: object(
190+
user: Expression::stringFieldPath('user'),
191+
genre: Expression::stringFieldPath('genres'),
192+
),
193+
);
194+
}
195+
}

0 commit comments

Comments
 (0)