mirror of https://github.com/mongodb/mongo
130 lines
4.4 KiB
JavaScript
130 lines
4.4 KiB
JavaScript
/**
|
|
* Basic integration tests for the $let expression.
|
|
*/
|
|
import {assertErrorCode} from "jstests/aggregation/extras/utils.js";
|
|
|
|
let coll = db.agg_expr_let;
|
|
coll.drop();
|
|
assert.commandWorked(coll.insert({zero: 0, one: 1, two: 2, three: 3, nested: {four: 4}}));
|
|
|
|
function testExpr(expression, output) {
|
|
const res = coll.aggregate([{$project: {output: expression}}]).toArray();
|
|
assert.eq(res.length, 1, tojson(res));
|
|
assert.eq(res[0].output, output, tojson(res));
|
|
|
|
// Test in group:
|
|
const result = coll.aggregate({$group: {_id: 0, res: {$sum: expression}}}).toArray();
|
|
assert.eq(result, [{_id: 0, res: output}]);
|
|
}
|
|
|
|
// Basic tests.
|
|
testExpr("$two", 2);
|
|
testExpr("$$CURRENT.two", 2);
|
|
testExpr("$$ROOT.two", 2);
|
|
|
|
// Using sub expressions.
|
|
testExpr({$add: ["$two", "$$CURRENT.three"]}, 5);
|
|
testExpr({$add: ["$$CURRENT.two", "$$ROOT.nested.four"]}, 6);
|
|
|
|
// Verify that the variables defined in $let work.
|
|
testExpr({$let: {vars: {a: 10}, in: "$$a"}}, 10);
|
|
testExpr({$let: {vars: {a: "$zero"}, in: "$$a"}}, 0);
|
|
testExpr({$let: {vars: {a: {$add: ["$one", "$two"]}, b: 10}, in: {$multiply: ["$$a", "$$b"]}}}, 30);
|
|
|
|
// Verify that the outer level variable works in inner level $let.
|
|
testExpr(
|
|
{
|
|
$let: {vars: {var1: 1}, in: {$let: {vars: {var2: "$$var1"}, in: {$sum: ["$$var1", "$$var2"]}}}},
|
|
},
|
|
2,
|
|
);
|
|
|
|
// Verify that the outer level variables get overwritten by inner level variables.
|
|
testExpr(
|
|
{
|
|
$let: {
|
|
vars: {var1: "$one"},
|
|
in: {$let: {vars: {var2: "$$var1", var1: 3}, in: {$sum: ["$$var2", "$$var1"]}}},
|
|
},
|
|
},
|
|
4,
|
|
);
|
|
|
|
// $let changing CURRENT
|
|
testExpr({$let: {vars: {CURRENT: "$$ROOT.nested"}, in: {$multiply: ["$four", "$$ROOT.two"]}}}, 8);
|
|
testExpr(
|
|
{
|
|
$let: {
|
|
vars: {CURRENT: "$$CURRENT.nested"}, // using original value of CURRENT
|
|
in: {$multiply: ["$four", "$$ROOT.two"]},
|
|
},
|
|
},
|
|
8,
|
|
);
|
|
testExpr(
|
|
{
|
|
$let: {
|
|
vars: {CURRENT: "$nested"}, // same as last
|
|
in: {$multiply: ["$four", "$$ROOT.two"]},
|
|
},
|
|
},
|
|
8,
|
|
);
|
|
testExpr(
|
|
{
|
|
$let: {
|
|
vars: {CURRENT: {$const: {ten: 10}}}, // "artificial" object
|
|
in: {$multiply: ["$ten", "$$ROOT.two"]},
|
|
},
|
|
},
|
|
20,
|
|
);
|
|
testExpr(
|
|
{
|
|
$let: {
|
|
vars: {CURRENT: "$three"}, // sets current to the number 3 (not an object)
|
|
in: {$multiply: ["$$CURRENT", "$$ROOT.two"]},
|
|
},
|
|
},
|
|
6,
|
|
);
|
|
|
|
// Swapping with $let (ensures there is no ordering dependency in vars).
|
|
testExpr(
|
|
{
|
|
$let: {
|
|
vars: {x: 6, y: 10},
|
|
in: {
|
|
$let: {
|
|
vars: {x: "$$y", y: "$$x"}, // now {x:10, y:6}
|
|
in: {$subtract: ["$$x", "$$y"]},
|
|
},
|
|
},
|
|
},
|
|
}, // Not commutative!
|
|
4,
|
|
); // 10-6 not 6-10 or 6-6
|
|
|
|
// Unicode is allowed.
|
|
testExpr({$let: {vars: {"日本語": 10}, in: "$$日本語"}}, 10); // Japanese for "Japanese language".
|
|
|
|
// Can use ROOT and CURRENT directly with no subfield (SERVER-5916).
|
|
coll.drop();
|
|
coll.insert({_id: "obj"});
|
|
assert.eq(coll.aggregate({$project: {_id: 0, obj: "$$ROOT"}}).toArray(), [{obj: {_id: "obj"}}]);
|
|
assert.eq(coll.aggregate({$project: {_id: 0, obj: "$$CURRENT"}}).toArray(), [{obj: {_id: "obj"}}]);
|
|
assert.eq(coll.aggregate({$group: {_id: 0, objs: {$push: "$$ROOT"}}}).toArray(), [{_id: 0, objs: [{_id: "obj"}]}]);
|
|
assert.eq(coll.aggregate({$group: {_id: 0, objs: {$push: "$$CURRENT"}}}).toArray(), [{_id: 0, objs: [{_id: "obj"}]}]);
|
|
|
|
// Check name validity checks.
|
|
assertErrorCode(coll, {$project: {a: {$let: {vars: {ROOT: 1}, in: "$$ROOT"}}}}, ErrorCodes.FailedToParse);
|
|
assertErrorCode(coll, {$project: {a: {$let: {vars: {FOO: 1}, in: "$$FOO"}}}}, ErrorCodes.FailedToParse);
|
|
assertErrorCode(coll, {$project: {a: {$let: {vars: {_underbar: 1}, in: "$$FOO"}}}}, ErrorCodes.FailedToParse);
|
|
assertErrorCode(coll, {$project: {a: {$let: {vars: {"a.b": 1}, in: "$$FOO"}}}}, ErrorCodes.FailedToParse);
|
|
assertErrorCode(coll, {$project: {a: {$let: {vars: {"a b": 1}, in: "$$FOO"}}}}, ErrorCodes.FailedToParse);
|
|
assertErrorCode(coll, {$project: {a: "$$_underbar"}}, ErrorCodes.FailedToParse);
|
|
assertErrorCode(coll, {$project: {a: "$$with spaces"}}, ErrorCodes.FailedToParse);
|
|
|
|
// Verify that variables defined in '$let' cannot be used to initialize other variables.
|
|
assertErrorCode(coll, [{$project: {output: {$let: {vars: {var1: "$one", var2: "$$var1"}, in: "$$var1"}}}}], 17276);
|