mirror of https://github.com/mongodb/mongo
140 lines
4.1 KiB
JavaScript
140 lines
4.1 KiB
JavaScript
// In SERVER-17258, the $reduce expression was introduced. In this test file, we check the
|
|
// functionality and error cases of the expression.
|
|
import {assertErrorCode, testExpression} from "jstests/aggregation/extras/utils.js";
|
|
|
|
let coll = db.reduce;
|
|
|
|
testExpression(coll, {$reduce: {input: [1, 2, 3], initialValue: {$literal: 0}, in: {$sum: ["$$this", "$$value"]}}}, 6);
|
|
testExpression(coll, {$reduce: {input: [], initialValue: {$literal: 0}, in: 10}}, 0);
|
|
testExpression(
|
|
coll,
|
|
{$reduce: {input: [1, 2, 3], initialValue: [], in: {$concatArrays: ["$$value", ["$$this"]]}}},
|
|
[1, 2, 3],
|
|
);
|
|
testExpression(
|
|
coll,
|
|
{
|
|
$reduce: {
|
|
input: [1, 2],
|
|
initialValue: [],
|
|
in: {$concatArrays: ["$$value", ["$$value.notAField"]]},
|
|
},
|
|
},
|
|
[[], []],
|
|
);
|
|
|
|
// A nested $reduce which sums each subarray, then multiplies the results.
|
|
testExpression(
|
|
coll,
|
|
{
|
|
$reduce: {
|
|
input: [
|
|
[1, 2, 3],
|
|
[4, 5],
|
|
],
|
|
initialValue: 1,
|
|
in: {
|
|
$multiply: [
|
|
"$$value",
|
|
{
|
|
$reduce: {
|
|
input: "$$this",
|
|
initialValue: 0,
|
|
in: {$sum: ["$$value", "$$this"]},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
54,
|
|
);
|
|
|
|
// A nested $reduce using a $let to allow the inner $reduce to access the variables of the
|
|
// outer.
|
|
testExpression(
|
|
coll,
|
|
{
|
|
$reduce: {
|
|
input: [
|
|
[0, 1],
|
|
[2, 3],
|
|
],
|
|
initialValue: {allElements: [], sumOfInner: {$literal: 0}},
|
|
in: {
|
|
$let: {
|
|
vars: {outerValue: "$$value", innerArray: "$$this"},
|
|
in: {
|
|
$reduce: {
|
|
input: "$$innerArray",
|
|
initialValue: "$$outerValue",
|
|
in: {
|
|
allElements: {
|
|
$concatArrays: ["$$value.allElements", ["$$this"]],
|
|
},
|
|
sumOfInner: {$sum: ["$$value.sumOfInner", "$$this"]},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{allElements: [0, 1, 2, 3], sumOfInner: 6},
|
|
);
|
|
|
|
// Nullish input produces null as an output.
|
|
testExpression(coll, {$reduce: {input: null, initialValue: {$literal: 0}, in: 5}}, null);
|
|
testExpression(coll, {$reduce: {input: "$nonexistent", initialValue: {$literal: 0}, in: 5}}, null);
|
|
|
|
// Error cases for $reduce.
|
|
|
|
// $reduce requires an object.
|
|
let pipeline = {$project: {reduced: {$reduce: 0}}};
|
|
assertErrorCode(coll, pipeline, 40075);
|
|
|
|
// Unknown field specified.
|
|
pipeline = {
|
|
$project: {
|
|
reduced: {
|
|
$reduce: {
|
|
input: {$literal: 0},
|
|
initialValue: {$literal: 0},
|
|
in: {$literal: 0},
|
|
notAField: {$literal: 0},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
assertErrorCode(coll, pipeline, 40076);
|
|
|
|
// $reduce requires input to be specified.
|
|
pipeline = {
|
|
$project: {reduced: {$reduce: {initialValue: {$literal: 0}, in: {$literal: 0}}}},
|
|
};
|
|
assertErrorCode(coll, pipeline, 40077);
|
|
|
|
// $reduce requires initialValue to be specified.
|
|
pipeline = {
|
|
$project: {reduced: {$reduce: {input: {$literal: 0}, in: {$literal: 0}}}},
|
|
};
|
|
assertErrorCode(coll, pipeline, 40078);
|
|
|
|
// $reduce requires in to be specified.
|
|
pipeline = {
|
|
$project: {reduced: {$reduce: {input: {$literal: 0}, initialValue: {$literal: 0}}}},
|
|
};
|
|
assertErrorCode(coll, pipeline, 40079);
|
|
|
|
// $$value is undefined in the non-'in' arguments of $reduce.
|
|
pipeline = {
|
|
$project: {reduced: {$reduce: {input: "$$value", initialValue: [], in: []}}},
|
|
};
|
|
assertErrorCode(coll, pipeline, 17276);
|
|
|
|
// $$this is undefined in the non-'in' arguments of $reduce.
|
|
pipeline = {
|
|
$project: {reduced: {$reduce: {input: "$$this", initialValue: [], in: []}}},
|
|
};
|
|
assertErrorCode(coll, pipeline, 17276);
|