@@ -127,41 +127,128 @@ public void mapTest() {
127
127
"{'$map': {'input': [true, true, false], 'in': {'$not': '$$this'}}}" );
128
128
}
129
129
130
+ // https://www.mongodb.com/docs/manual/reference/operator/aggregation/reduce/
131
+ // reduce is implemented as each individual type of reduction (monoid)
132
+ // this prevents issues related to incorrect specification of identity values
133
+
130
134
@ Test
131
- public void reduceTest () {
132
- // https://www.mongodb.com/docs/manual/reference/operator/aggregation/reduce/
135
+ public void reduceAnyTest () {
133
136
assertExpression (
134
- Stream .of (true , true , false )
135
- .reduce (false , (a , b ) -> a || b ),
136
- arrayTTF .reduce (of (false ), (a , b ) -> a .or (b )),
137
- // MQL:
138
- "{'$reduce': {'input': [true, true, false], 'initialValue': false, 'in': {'$or': ['$$value', '$$this']}}}" );
137
+ true ,
138
+ arrayTTF .any (a -> a ),
139
+ "{'$reduce': {'input': {'$map': {'input': [true, true, false], 'in': '$$this'}}, "
140
+ + "'initialValue': false, 'in': {'$or': ['$$value', '$$this']}}}" );
139
141
assertExpression (
140
- Stream .of (true , true , false )
141
- .reduce (true , (a , b ) -> a && b ),
142
- arrayTTF .reduce (of (true ), (a , b ) -> a .and (b )),
143
- // MQL:
144
- "{'$reduce': {'input': [true, true, false], 'initialValue': true, 'in': {'$and': ['$$value', '$$this']}}}" );
145
- // empty array
142
+ false ,
143
+ ofBooleanArray ().any (a -> a ));
144
+
146
145
assertExpression (
147
- Stream .<Boolean >empty ().reduce (true , (a , b ) -> a && b ),
148
- ofBooleanArray ().reduce (of (true ), (a , b ) -> a .and (b )),
149
- // MQL:
150
- "{'$reduce': {'input': [], 'initialValue': true, 'in': {'$and': ['$$value', '$$this']}}}" );
151
- // constant result
146
+ true ,
147
+ ofIntegerArray (1 , 2 , 3 ).any (a -> a .eq (of (3 ))));
152
148
assertExpression (
153
- Stream .of (true , true , false )
154
- .reduce (true , (a , b ) -> true ),
155
- arrayTTF .reduce (of (true ), (a , b ) -> of (true )),
156
- // MQL:
157
- "{'$reduce': {'input': [true, true, false], 'initialValue': true, 'in': true}}" );
158
- // non-commutative
149
+ false ,
150
+ ofIntegerArray (1 , 2 , 2 ).any (a -> a .eq (of (9 ))));
151
+ }
152
+
153
+ @ Test
154
+ public void reduceAllTest () {
155
+ assertExpression (
156
+ false ,
157
+ arrayTTF .all (a -> a ),
158
+ "{'$reduce': {'input': {'$map': {'input': [true, true, false], 'in': '$$this'}}, "
159
+ + "'initialValue': true, 'in': {'$and': ['$$value', '$$this']}}}" );
160
+ assertExpression (
161
+ true ,
162
+ ofBooleanArray ().all (a -> a ));
163
+
164
+ assertExpression (
165
+ true ,
166
+ ofIntegerArray (1 , 2 , 3 ).all (a -> a .gt (of (0 ))));
167
+ assertExpression (
168
+ false ,
169
+ ofIntegerArray (1 , 2 , 2 ).all (a -> a .eq (of (2 ))));
170
+ }
171
+
172
+ @ Test
173
+ public void reduceSumTest () {
174
+ assertExpression (
175
+ 6 ,
176
+ ofIntegerArray (1 , 2 , 3 ).sum (a -> a ),
177
+ "{'$reduce': {'input': {'$map': {'input': [1, 2, 3], 'in': '$$this'}}, "
178
+ + "'initialValue': 0, 'in': {'$add': ['$$value', '$$this']}}}" );
179
+ // empty array:
180
+ assertExpression (
181
+ 0 ,
182
+ ofIntegerArray ().sum (a -> a ));
183
+ }
184
+
185
+ @ Test
186
+ public void reduceMaxTest () {
187
+ assertExpression (
188
+ 3 ,
189
+ 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]}" );
195
+ assertExpression (
196
+ 9 ,
197
+ ofIntegerArray ().max (a -> a , of (9 )));
198
+ }
199
+
200
+ @ Test
201
+ public void reduceMinTest () {
202
+ assertExpression (
203
+ 1 ,
204
+ 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]}" );
210
+ assertExpression (
211
+ 9 ,
212
+ ofIntegerArray ().min (a -> a , of (9 )));
213
+ }
214
+
215
+ @ Test
216
+ public void reduceJoinTest () {
159
217
assertExpression (
160
218
"abc" ,
161
- ofStringArray ("a" , "b" , "c" ).reduce (of ("" ), (a , b ) -> a .concat (b )),
162
- // MQL:
163
- "{'$reduce': {'input': ['a', 'b', 'c'], 'initialValue': '', 'in': {'$concat': ['$$value', '$$this']}}}" );
219
+ ofStringArray ("a" , "b" , "c" ).join (a -> a ),
220
+ "{'$reduce': {'input': {'$map': {'input': ['a', 'b', 'c'], 'in': '$$this'}}, "
221
+ + "'initialValue': '', 'in': {'$concat': ['$$value', '$$this']}}}" );
222
+ assertExpression (
223
+ "" ,
224
+ ofStringArray ().join (a -> a ));
225
+ }
164
226
227
+ @ Test
228
+ public void reduceConcatTest () {
229
+ assertExpression (
230
+ Arrays .asList (1 , 2 , 3 , 4 ),
231
+ ofArray (ofIntegerArray (1 , 2 ), ofIntegerArray (3 , 4 )).concat (v -> v ),
232
+ "{'$reduce': {'input': {'$map': {'input': [[1, 2], [3, 4]], 'in': '$$this'}}, "
233
+ + "'initialValue': [], "
234
+ + "'in': {'$concatArrays': ['$$value', '$$this']}}} " );
235
+ // empty:
236
+ ArrayExpression <ArrayExpression <Expression >> expressionArrayExpression = ofArray ();
237
+ assertExpression (
238
+ Collections .emptyList (),
239
+ expressionArrayExpression .concat (a -> a ));
240
+ }
241
+
242
+ @ Test
243
+ public void reduceUnionTest () {
244
+ // https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/ (40)
245
+ assertExpression (
246
+ Arrays .asList (1 , 2 , 3 ),
247
+ ofArray (ofIntegerArray (1 , 2 ), ofIntegerArray (1 , 3 )).union (v -> v ),
248
+ // MQL:
249
+ "{'$reduce': {'input': {'$map': {'input': [[1, 2], [1, 3]], 'in': '$$this'}}, "
250
+ + "'initialValue': [], "
251
+ + "'in': {'$setUnion': ['$$value', '$$this']}}}" );
165
252
}
166
253
167
254
@ Test
@@ -221,6 +308,12 @@ public void firstTest() {
221
308
array123 .first (),
222
309
// MQL:
223
310
"{'$first': [[1, 2, 3]]}" );
311
+
312
+ assertExpression (
313
+ MISSING ,
314
+ ofIntegerArray ().first (),
315
+ // MQL:
316
+ "{'$first': [[]]}" );
224
317
}
225
318
226
319
@ Test
@@ -289,7 +382,7 @@ public void sliceTest() {
289
382
}
290
383
291
384
@ Test
292
- public void setUnionTest () {
385
+ public void unionTest () {
293
386
// https://www.mongodb.com/docs/manual/reference/operator/aggregation/setUnion/
294
387
assertExpression (
295
388
Arrays .asList (1 , 2 , 3 ),
@@ -309,5 +402,4 @@ public void setUnionTest() {
309
402
// MQL:
310
403
"{'$setUnion': [[1, 2, 1, 3, 3]]}" );
311
404
}
312
-
313
405
}
0 commit comments