33namespace MongoDB \Laravel \Tests \Eloquent ;
44
55use Illuminate \Database \Eloquent \Builder ;
6+ use Illuminate \Support \Collection ;
67use Illuminate \Support \Facades \DB ;
78use MongoDB \Laravel \Eloquent \Model ;
89use MongoDB \Laravel \Tests \TestCase ;
910
1011use function count ;
12+ use function ksort ;
1113
1214class EloquentWithAggregateTest extends TestCase
1315{
1416 protected function tearDown (): void
1517 {
16- EloquentWithCountModel1 ::truncate ();
17- EloquentWithCountModel2 ::truncate ();
18- EloquentWithCountModel3 ::truncate ();
19- EloquentWithCountModel4 ::truncate ();
18+ EloquentWithAggregateModel1 ::truncate ();
19+ EloquentWithAggregateModel2 ::truncate ();
20+ EloquentWithAggregateModel3 ::truncate ();
21+ EloquentWithAggregateModel4 ::truncate ();
2022
2123 parent ::tearDown ();
2224 }
2325
2426 public function testWithAggregate ()
2527 {
26- EloquentWithCountModel1 ::create (['id ' => 1 ]);
27- $ one = EloquentWithCountModel1 ::create (['id ' => 2 ]);
28+ EloquentWithAggregateModel1 ::create (['id ' => 1 ]);
29+ $ one = EloquentWithAggregateModel1 ::create (['id ' => 2 ]);
2830 $ one ->twos ()->create (['value ' => 4 ]);
2931 $ one ->twos ()->create (['value ' => 6 ]);
3032
31- $ results = EloquentWithCountModel1 ::withCount ('twos ' )->where ('id ' , 2 );
32- $ this -> assertSame ([
33+ $ results = EloquentWithAggregateModel1 ::withCount ('twos ' )->where ('id ' , 2 );
34+ self :: assertSameResults ([
3335 ['id ' => 2 , 'twos_count ' => 2 ],
34- ], $ results ->get ()-> toArray () );
36+ ], $ results ->get ());
3537
36- $ results = EloquentWithCountModel1 ::withMax ('twos ' , 'value ' )->where ('id ' , 2 );
37- $ this -> assertSame ([
38+ $ results = EloquentWithAggregateModel1 ::withMax ('twos ' , 'value ' )->where ('id ' , 2 );
39+ self :: assertSameResults ([
3840 ['id ' => 2 , 'twos_max ' => 6 ],
39- ], $ results ->get ()-> toArray () );
41+ ], $ results ->get ());
4042
41- $ results = EloquentWithCountModel1 ::withMin ('twos ' , 'value ' )->where ('id ' , 2 );
42- $ this -> assertSame ([
43+ $ results = EloquentWithAggregateModel1 ::withMin ('twos ' , 'value ' )->where ('id ' , 2 );
44+ self :: assertSameResults ([
4345 ['id ' => 2 , 'twos_min ' => 4 ],
44- ], $ results ->get ()-> toArray () );
46+ ], $ results ->get ());
4547
46- $ results = EloquentWithCountModel1 ::withAvg ('twos ' , 'value ' )->where ('id ' , 2 );
47- $ this -> assertSame ([
48+ $ results = EloquentWithAggregateModel1 ::withAvg ('twos ' , 'value ' )->where ('id ' , 2 );
49+ self :: assertSameResults ([
4850 ['id ' => 2 , 'twos_avg ' => 5.0 ],
49- ], $ results ->get ()->toArray ());
51+ ], $ results ->get ());
52+ }
53+
54+ public function testWithAggregateEmbed ()
55+ {
56+ EloquentWithAggregateModel1::create (['id ' => 1 ]);
57+ $ one = EloquentWithAggregateModel1::create (['id ' => 2 ]);
58+ $ one ->embeddeds ()->create (['value ' => 4 ]);
59+ $ one ->embeddeds ()->create (['value ' => 6 ]);
60+
61+ $ results = EloquentWithAggregateModel1::withCount ('embeddeds ' )->select ('id ' )->where ('id ' , 2 );
62+ self ::assertSameResults ([
63+ ['id ' => 2 , 'embeddeds_count ' => 2 ],
64+ ], $ results ->get ());
65+
66+ $ results = EloquentWithAggregateModel1::withMax ('embeddeds ' , 'value ' )->select ('id ' )->where ('id ' , 2 );
67+ self ::assertSameResults ([
68+ ['id ' => 2 , 'embeddeds_max ' => 6 ],
69+ ], $ results ->get ());
70+
71+ $ results = EloquentWithAggregateModel1::withMin ('embeddeds ' , 'value ' )->select ('id ' )->where ('id ' , 2 );
72+ self ::assertSameResults ([
73+ ['id ' => 2 , 'embeddeds_min ' => 4 ],
74+ ], $ results ->get ());
75+
76+ $ results = EloquentWithAggregateModel1::withAvg ('embeddeds ' , 'value ' )->select ('id ' )->where ('id ' , 2 );
77+ self ::assertSameResults ([
78+ ['id ' => 2 , 'embeddeds_avg ' => 5.0 ],
79+ ], $ results ->get ());
5080 }
5181
5282 public function testWithAggregateFiltered ()
5383 {
54- EloquentWithCountModel1 ::create (['id ' => 1 ]);
55- $ one = EloquentWithCountModel1 ::create (['id ' => 2 ]);
84+ EloquentWithAggregateModel1 ::create (['id ' => 1 ]);
85+ $ one = EloquentWithAggregateModel1 ::create (['id ' => 2 ]);
5686 $ one ->twos ()->create (['value ' => 4 ]);
5787 $ one ->twos ()->create (['value ' => 6 ]);
5888 $ one ->twos ()->create (['value ' => 8 ]);
5989 $ filter = static function (Builder $ query ) {
6090 $ query ->where ('value ' , '<= ' , 6 );
6191 };
6292
63- $ results = EloquentWithCountModel1 ::withCount (['twos ' => $ filter ])->where ('id ' , 2 );
64- $ this -> assertSame ([
93+ $ results = EloquentWithAggregateModel1 ::withCount (['twos ' => $ filter ])->where ('id ' , 2 );
94+ self :: assertSameResults ([
6595 ['id ' => 2 , 'twos_count ' => 2 ],
66- ], $ results ->get ()-> toArray () );
96+ ], $ results ->get ());
6797
68- $ results = EloquentWithCountModel1 ::withMax (['twos ' => $ filter ], 'value ' )->where ('id ' , 2 );
69- $ this -> assertSame ([
98+ $ results = EloquentWithAggregateModel1 ::withMax (['twos ' => $ filter ], 'value ' )->where ('id ' , 2 );
99+ self :: assertSameResults ([
70100 ['id ' => 2 , 'twos_max ' => 6 ],
71- ], $ results ->get ()-> toArray () );
101+ ], $ results ->get ());
72102
73- $ results = EloquentWithCountModel1 ::withMin (['twos ' => $ filter ], 'value ' )->where ('id ' , 2 );
74- $ this -> assertSame ([
103+ $ results = EloquentWithAggregateModel1 ::withMin (['twos ' => $ filter ], 'value ' )->where ('id ' , 2 );
104+ self :: assertSameResults ([
75105 ['id ' => 2 , 'twos_min ' => 4 ],
76- ], $ results ->get ()-> toArray () );
106+ ], $ results ->get ());
77107
78- $ results = EloquentWithCountModel1 ::withAvg (['twos ' => $ filter ], 'value ' )->where ('id ' , 2 );
79- $ this -> assertSame ([
108+ $ results = EloquentWithAggregateModel1 ::withAvg (['twos ' => $ filter ], 'value ' )->where ('id ' , 2 );
109+ self :: assertSameResults ([
80110 ['id ' => 2 , 'twos_avg ' => 5.0 ],
81- ], $ results ->get ()->toArray ());
111+ ], $ results ->get ());
112+ }
113+
114+ public function testWithAggregateEmbedFiltered ()
115+ {
116+ self ::markTestSkipped ('EmbedsMany does not support filtering. $filter requires an expression but the Query Builder generates query predicates. ' );
117+
118+ EloquentWithAggregateModel1::create (['id ' => 1 ]);
119+ $ one = EloquentWithAggregateModel1::create (['id ' => 2 ]);
120+ $ one ->embeddeds ()->create (['value ' => 4 ]);
121+ $ one ->embeddeds ()->create (['value ' => 6 ]);
122+ $ one ->embeddeds ()->create (['value ' => 8 ]);
123+ $ filter = static function (Builder $ query ) {
124+ $ query ->where ('value ' , '<= ' , 6 );
125+ };
126+
127+ $ results = EloquentWithAggregateModel1::withCount (['embeddeds ' => $ filter ])->where ('id ' , 2 );
128+ self ::assertSameResults ([
129+ ['id ' => 2 , 'embeddeds_count ' => 2 ],
130+ ], $ results ->get ());
131+
132+ $ results = EloquentWithAggregateModel1::withMax (['embeddeds ' => $ filter ], 'value ' )->where ('id ' , 2 );
133+ self ::assertSameResults ([
134+ ['id ' => 2 , 'embeddeds_max ' => 6 ],
135+ ], $ results ->get ());
136+
137+ $ results = EloquentWithAggregateModel1::withMin (['embeddeds ' => $ filter ], 'value ' )->where ('id ' , 2 );
138+ self ::assertSameResults ([
139+ ['id ' => 2 , 'embeddeds_min ' => 4 ],
140+ ], $ results ->get ());
141+
142+ $ results = EloquentWithAggregateModel1::withAvg (['embeddeds ' => $ filter ], 'value ' )->where ('id ' , 2 );
143+ self ::assertSameResults ([
144+ ['id ' => 2 , 'embeddeds_avg ' => 5.0 ],
145+ ], $ results ->get ());
82146 }
83147
84148 public function testWithAggregateMultipleResults ()
85149 {
86150 $ connection = DB ::connection ('mongodb ' );
87151 $ ones = [
88- EloquentWithCountModel1 ::create (['id ' => 1 ]),
89- EloquentWithCountModel1 ::create (['id ' => 2 ]),
90- EloquentWithCountModel1 ::create (['id ' => 3 ]),
91- EloquentWithCountModel1 ::create (['id ' => 4 ]),
152+ EloquentWithAggregateModel1 ::create (['id ' => 1 ]),
153+ EloquentWithAggregateModel1 ::create (['id ' => 2 ]),
154+ EloquentWithAggregateModel1 ::create (['id ' => 3 ]),
155+ EloquentWithAggregateModel1 ::create (['id ' => 4 ]),
92156 ];
93157
94158 $ ones [0 ]->twos ()->create (['value ' => 1 ]);
@@ -101,88 +165,103 @@ public function testWithAggregateMultipleResults()
101165 $ connection ->enableQueryLog ();
102166
103167 // Count
104- $ results = EloquentWithCountModel1 ::withCount ([
168+ $ results = EloquentWithAggregateModel1 ::withCount ([
105169 'twos ' => function ($ query ) {
106170 $ query ->where ('value ' , '>= ' , 2 );
107171 },
108172 ]);
109173
110- $ this -> assertSame ([
174+ self :: assertSameResults ([
111175 ['id ' => 1 , 'twos_count ' => 2 ],
112176 ['id ' => 2 , 'twos_count ' => 0 ],
113177 ['id ' => 3 , 'twos_count ' => 1 ],
114178 ['id ' => 4 , 'twos_count ' => 0 ],
115- ], $ results ->get ()-> toArray () );
179+ ], $ results ->get ());
116180
117- $ this -> assertSame (2 , count ($ connection ->getQueryLog ()));
181+ self :: assertSame (2 , count ($ connection ->getQueryLog ()));
118182 $ connection ->flushQueryLog ();
119183
120184 // Max
121- $ results = EloquentWithCountModel1 ::withMax ([
185+ $ results = EloquentWithAggregateModel1 ::withMax ([
122186 'twos ' => function ($ query ) {
123187 $ query ->where ('value ' , '>= ' , 2 );
124188 },
125189 ], 'value ' );
126190
127- $ this -> assertSame ([
191+ self :: assertSameResults ([
128192 ['id ' => 1 , 'twos_max ' => 3 ],
129193 ['id ' => 2 , 'twos_max ' => null ],
130194 ['id ' => 3 , 'twos_max ' => 2 ],
131195 ['id ' => 4 , 'twos_max ' => null ],
132- ], $ results ->get ()-> toArray () );
196+ ], $ results ->get ());
133197
134- $ this -> assertSame (2 , count ($ connection ->getQueryLog ()));
198+ self :: assertSame (2 , count ($ connection ->getQueryLog ()));
135199 $ connection ->flushQueryLog ();
136200
137201 // Min
138- $ results = EloquentWithCountModel1 ::withMin ([
202+ $ results = EloquentWithAggregateModel1 ::withMin ([
139203 'twos ' => function ($ query ) {
140204 $ query ->where ('value ' , '>= ' , 2 );
141205 },
142206 ], 'value ' );
143207
144- $ this -> assertSame ([
208+ self :: assertSameResults ([
145209 ['id ' => 1 , 'twos_min ' => 2 ],
146210 ['id ' => 2 , 'twos_min ' => null ],
147211 ['id ' => 3 , 'twos_min ' => 2 ],
148212 ['id ' => 4 , 'twos_min ' => null ],
149- ], $ results ->get ()-> toArray () );
213+ ], $ results ->get ());
150214
151- $ this -> assertSame (2 , count ($ connection ->getQueryLog ()));
215+ self :: assertSame (2 , count ($ connection ->getQueryLog ()));
152216 $ connection ->flushQueryLog ();
153217
154218 // Avg
155- $ results = EloquentWithCountModel1 ::withAvg ([
219+ $ results = EloquentWithAggregateModel1 ::withAvg ([
156220 'twos ' => function ($ query ) {
157221 $ query ->where ('value ' , '>= ' , 2 );
158222 },
159223 ], 'value ' );
160224
161- $ this -> assertSame ([
225+ self :: assertSameResults ([
162226 ['id ' => 1 , 'twos_avg ' => 2.5 ],
163227 ['id ' => 2 , 'twos_avg ' => null ],
164228 ['id ' => 3 , 'twos_avg ' => 2.0 ],
165229 ['id ' => 4 , 'twos_avg ' => null ],
166- ], $ results ->get ()-> toArray () );
230+ ], $ results ->get ());
167231
168- $ this -> assertSame (2 , count ($ connection ->getQueryLog ()));
232+ self :: assertSame (2 , count ($ connection ->getQueryLog ()));
169233 $ connection ->flushQueryLog ();
170234 }
171235
172236 public function testGlobalScopes ()
173237 {
174- $ one = EloquentWithCountModel1 ::create ();
238+ $ one = EloquentWithAggregateModel1 ::create ();
175239 $ one ->fours ()->create ();
176240
177- $ result = EloquentWithCountModel1::withCount ('fours ' )->first ();
178- $ this ->assertSame (0 , $ result ->fours_count );
241+ $ result = EloquentWithAggregateModel1::withCount ('fours ' )->first ();
242+ self ::assertSame (0 , $ result ->fours_count );
243+
244+ $ result = EloquentWithAggregateModel1::withCount ('allFours ' )->first ();
245+ self ::assertSame (1 , $ result ->all_fours_count );
246+ }
247+
248+ private static function assertSameResults (array $ expected , Collection $ collection )
249+ {
250+ $ actual = $ collection ->toArray ();
251+
252+ foreach ($ actual as &$ item ) {
253+ ksort ($ item );
254+ }
255+
256+ foreach ($ expected as &$ item ) {
257+ ksort ($ item );
258+ }
179259
180- $ result = EloquentWithCountModel1::withCount ('allFours ' )->first ();
181- $ this ->assertSame (1 , $ result ->all_fours_count );
260+ self ::assertSame ($ expected , $ actual );
182261 }
183262}
184263
185- class EloquentWithCountModel1 extends Model
264+ class EloquentWithAggregateModel1 extends Model
186265{
187266 protected $ connection = 'mongodb ' ;
188267 public $ table = 'one ' ;
@@ -191,21 +270,26 @@ class EloquentWithCountModel1 extends Model
191270
192271 public function twos ()
193272 {
194- return $ this ->hasMany (EloquentWithCountModel2 ::class, 'one_id ' );
273+ return $ this ->hasMany (EloquentWithAggregateModel2 ::class, 'one_id ' );
195274 }
196275
197276 public function fours ()
198277 {
199- return $ this ->hasMany (EloquentWithCountModel4 ::class, 'one_id ' );
278+ return $ this ->hasMany (EloquentWithAggregateModel4 ::class, 'one_id ' );
200279 }
201280
202281 public function allFours ()
203282 {
204283 return $ this ->fours ()->withoutGlobalScopes ();
205284 }
285+
286+ public function embeddeds ()
287+ {
288+ return $ this ->embedsMany (EloquentWithAggregateEmbeddedModel::class);
289+ }
206290}
207291
208- class EloquentWithCountModel2 extends Model
292+ class EloquentWithAggregateModel2 extends Model
209293{
210294 protected $ connection = 'mongodb ' ;
211295 public $ table = 'two ' ;
@@ -224,11 +308,11 @@ protected static function boot()
224308
225309 public function threes ()
226310 {
227- return $ this ->hasMany (EloquentWithCountModel3 ::class, 'two_id ' );
311+ return $ this ->hasMany (EloquentWithAggregateModel3 ::class, 'two_id ' );
228312 }
229313}
230314
231- class EloquentWithCountModel3 extends Model
315+ class EloquentWithAggregateModel3 extends Model
232316{
233317 protected $ connection = 'mongodb ' ;
234318 public $ table = 'three ' ;
@@ -245,7 +329,7 @@ protected static function boot()
245329 }
246330}
247331
248- class EloquentWithCountModel4 extends Model
332+ class EloquentWithAggregateModel4 extends Model
249333{
250334 protected $ connection = 'mongodb ' ;
251335 public $ table = 'four ' ;
@@ -261,3 +345,10 @@ protected static function boot()
261345 });
262346 }
263347}
348+
349+ class EloquentWithAggregateEmbeddedModel extends Model
350+ {
351+ protected $ connection = 'mongodb ' ;
352+ public $ timestamps = false ;
353+ protected $ guarded = [];
354+ }
0 commit comments