25
25
import java .util .Arrays ;
26
26
import java .util .Collections ;
27
27
import java .util .LinkedList ;
28
+ import java .util .function .Function ;
28
29
import java .util .stream .Collectors ;
29
30
import java .util .stream .Stream ;
30
31
37
38
import static com .mongodb .client .model .expressions .Expressions .ofStringArray ;
38
39
import static org .junit .jupiter .api .Assertions .assertThrows ;
39
40
40
- @ SuppressWarnings ({"ConstantConditions" , " Convert2MethodRef" })
41
+ @ SuppressWarnings ({"Convert2MethodRef" })
41
42
class ArrayExpressionsFunctionalTest extends AbstractExpressionsFunctionalTest {
42
43
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/#array-expression-operators
43
44
// (Incomplete)
@@ -127,6 +128,17 @@ public void mapTest() {
127
128
"{'$map': {'input': [true, true, false], 'in': {'$not': '$$this'}}}" );
128
129
}
129
130
131
+ @ Test
132
+ public void sortTest () {
133
+ // https://www.mongodb.com/docs/manual/reference/operator/aggregation/sortArray/
134
+ assertExpression (
135
+ Stream .of (3 , 1 , 2 )
136
+ .sorted ().collect (Collectors .toList ()),
137
+ ofIntegerArray (3 , 1 , 2 ).sort (),
138
+ // MQL:
139
+ "{'$sortArray': {'input': [3, 1, 2], 'sortBy': 1}}" );
140
+ }
141
+
130
142
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/reduce/
131
143
// reduce is implemented as each individual type of reduction (monoid)
132
144
// this prevents issues related to incorrect specification of identity values
@@ -187,11 +199,9 @@ public void reduceMaxTest() {
187
199
assertExpression (
188
200
3 ,
189
201
ofIntegerArray (1 , 2 , 3 ).max (a -> a , of (9 )),
190
- "{'$cond': [{'$isNumber': [{'$reduce': {'input': "
191
- + "{'$map': {'input': [1, 2, 3], 'in': '$$this'}}, "
192
- + "'initialValue': null, 'in': {'$max': ['$$value', '$$this']}}}]}, "
193
- + "{'$reduce': {'input': {'$map': {'input': [1, 2, 3], 'in': '$$this'}}, "
194
- + "'initialValue': null, 'in': {'$max': ['$$value', '$$this']}}}, 9]}" );
202
+ "{'$cond': [{'$eq': [{'$size': [[1, 2, 3]]}, 0]}, 9, "
203
+ + "{'$first': [{'$maxN': {'input': {'$map': {'input': {'$map': "
204
+ + "{'input': [1, 2, 3], 'in': '$$this'}}, 'in': '$$this'}}, 'n': 1}}]}]}" );
195
205
assertExpression (
196
206
9 ,
197
207
ofIntegerArray ().max (a -> a , of (9 )));
@@ -202,16 +212,42 @@ public void reduceMinTest() {
202
212
assertExpression (
203
213
1 ,
204
214
ofIntegerArray (1 , 2 , 3 ).min (a -> a , of (9 )),
205
- "{'$cond': [{'$isNumber': [{'$reduce': {'input': "
206
- + "{'$map': {'input': [1, 2, 3], 'in': '$$this'}}, "
207
- + "'initialValue': null, 'in': {'$min': ['$$value', '$$this']}}}]}, "
208
- + "{'$reduce': {'input': {'$map': {'input': [1, 2, 3], 'in': '$$this'}}, "
209
- + "'initialValue': null, 'in': {'$min': ['$$value', '$$this']}}}, 9]}" );
215
+ "{'$cond': [{'$eq': [{'$size': [[1, 2, 3]]}, 0]}, 9, "
216
+ + "{'$first': [{'$minN': {'input': {'$map': {'input': {'$map': "
217
+ + "{'input': [1, 2, 3], 'in': '$$this'}}, 'in': '$$this'}}, 'n': 1}}]}]}" );
210
218
assertExpression (
211
219
9 ,
212
220
ofIntegerArray ().min (a -> a , of (9 )));
213
221
}
214
222
223
+ @ Test
224
+ public void reduceMaxNTest () {
225
+ assertExpression (
226
+ Arrays .asList (3 , 2 ),
227
+ ofIntegerArray (3 , 1 , 2 ).maxN (of (2 ), a -> a ));
228
+ assertExpression (
229
+ Arrays .asList (),
230
+ ofIntegerArray ().maxN (of (2 ), a -> a ));
231
+ // N must be non-zero
232
+ assertThrows (MongoCommandException .class , () -> assertExpression (
233
+ Arrays .asList (),
234
+ ofIntegerArray (3 , 2 , 1 ).maxN (of (0 ), a -> a )));
235
+ }
236
+
237
+ @ Test
238
+ public void reduceMinNTest () {
239
+ assertExpression (
240
+ Arrays .asList (1 , 2 ),
241
+ ofIntegerArray (3 , 1 , 2 ).minN (of (2 ), a -> a ));
242
+ assertExpression (
243
+ Arrays .asList (),
244
+ ofIntegerArray ().minN (of (2 ), a -> a ));
245
+ // N must be non-zero
246
+ assertThrows (MongoCommandException .class , () -> assertExpression (
247
+ Arrays .asList (),
248
+ ofIntegerArray (3 , 2 , 1 ).minN (of (0 ), a -> a )));
249
+ }
250
+
215
251
@ Test
216
252
public void reduceJoinTest () {
217
253
assertExpression (
@@ -244,11 +280,18 @@ public void reduceUnionTest() {
244
280
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/ (40)
245
281
assertExpression (
246
282
Arrays .asList (1 , 2 , 3 ),
247
- ofArray (ofIntegerArray (1 , 2 ), ofIntegerArray (1 , 3 )).union (v -> v ),
283
+ ofArray (ofIntegerArray (1 , 2 ), ofIntegerArray (1 , 3 )).union (v -> v ). sort () ,
248
284
// MQL:
249
- "{'$reduce': {'input': {'$map': {'input': [[1, 2], [1, 3]], 'in': '$$this'}}, "
250
- + "'initialValue': [], "
251
- + "'in': {'$setUnion': ['$$value', '$$this']}}}" );
285
+ "{'$sortArray': {'input': {'$reduce': {'input': "
286
+ + "{'$map': {'input': [[1, 2], [1, 3]], 'in': '$$this'}}, "
287
+ + "'initialValue': [], 'in': {'$setUnion': ['$$value', '$$this']}}}, 'sortBy': 1}}" );
288
+
289
+ Function <ArrayExpression <? extends Expression >, ArrayExpression <IntegerExpression >> f = a ->
290
+ a .map (v -> v .isBooleanOr (of (false ))
291
+ .cond (of (1 ), of (0 )));
292
+ assertExpression (
293
+ Arrays .asList (0 , 1 ),
294
+ ofArray (ofBooleanArray (true , false ), ofBooleanArray (false )).union (f ));
252
295
}
253
296
254
297
@ Test
@@ -386,20 +429,20 @@ public void unionTest() {
386
429
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/
387
430
assertExpression (
388
431
Arrays .asList (1 , 2 , 3 ),
389
- array123 .union (array123 ),
432
+ array123 .union (array123 ). sort () ,
390
433
// MQL:
391
- "{'$setUnion': [[1, 2, 3], [1, 2, 3]]}" );
392
-
434
+ "{'$sortArray': {'input': {'$setUnion': [[1, 2, 3], [1, 2, 3]]}, 'sortBy': 1}}" );
393
435
// mixed types:
394
436
assertExpression (
395
437
Arrays .asList (1 , 2.0 , 3 ),
396
- // above is a set; in case of flakiness, below should `sort` (not implemented at time of test creation)
397
- ofNumberArray (2.0 ).union (ofIntegerArray (1 , 2 , 3 )));
398
- // convenience
438
+ ofNumberArray (2.0 ).union (ofIntegerArray (1 , 2 , 3 )).sort ());
439
+ }
440
+
441
+ @ Test
442
+ public void distinctTest () {
399
443
assertExpression (
400
444
Arrays .asList (1 , 2 , 3 ),
401
- ofIntegerArray (1 , 2 , 1 , 3 , 3 ).distinct (),
402
- // MQL:
403
- "{'$setUnion': [[1, 2, 1, 3, 3]]}" );
445
+ ofIntegerArray (1 , 2 , 1 , 3 , 3 ).distinct ().sort (),
446
+ "{'$sortArray': {'input': {'$setUnion': [[1, 2, 1, 3, 3]]}, 'sortBy': 1}}" );
404
447
}
405
448
}
0 commit comments