diff options
author | Sally McNichols <sally.mcnichols@mongodb.com> | 2016-06-30 14:13:27 -0400 |
---|---|---|
committer | Sally McNichols <sally.mcnichols@mongodb.com> | 2016-06-30 14:13:27 -0400 |
commit | f3919fcaa84bc10597df41d250a7493e2b378bba (patch) | |
tree | 0667329bfadabea0cd789f9d2e1ce336de654b84 | |
parent | cce13607bbd38814446e48d3433bbcf7acb26690 (diff) | |
download | mongo-f3919fcaa84bc10597df41d250a7493e2b378bba.tar.gz |
SERVER-24302 Make "as" option of $filter and $map default to "this"
-rw-r--r-- | jstests/aggregation/bugs/server17943.js | 22 | ||||
-rw-r--r-- | jstests/aggregation/bugs/server9841.js | 5 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.cpp | 12 |
3 files changed, 30 insertions, 9 deletions
diff --git a/jstests/aggregation/bugs/server17943.js b/jstests/aggregation/bugs/server17943.js index 7036a16b940..35d67d4fe20 100644 --- a/jstests/aggregation/bugs/server17943.js +++ b/jstests/aggregation/bugs/server17943.js @@ -31,6 +31,20 @@ load('jstests/aggregation/extras/utils.js'); var results = coll.aggregate([{$project: {b: {$filter: filterDoc}}}]).toArray(); assert.eq(results, expectedResults); + // create filter that uses the default variable name in 'cond' + filterDoc = {input: '$a', cond: {$eq: [2, '$$this']}}; + expectedResults = [ + {_id: 0, b: [2]}, + {_id: 1, b: [2]}, + {_id: 2, b: []}, + {_id: 3, b: []}, + {_id: 4, b: null}, + {_id: 5, b: null}, + {_id: 6, b: null}, + ]; + results = coll.aggregate([{$project: {b: {$filter: filterDoc}}}]).toArray(); + assert.eq(results, expectedResults); + // Invalid filter expressions. // Insert a document so that the initial cursor doesn't immediately return EOF. @@ -48,10 +62,6 @@ load('jstests/aggregation/extras/utils.js'); filterDoc = {as: 'x', cond: true}; assertErrorCode(coll, [{$project: {b: {$filter: filterDoc}}}], 28648); - // Missing 'as'. - filterDoc = {input: '$a', cond: true}; - assertErrorCode(coll, [{$project: {b: {$filter: filterDoc}}}], 28649); - // Missing 'cond'. filterDoc = {input: '$a', as: 'x'}; assertErrorCode(coll, [{$project: {b: {$filter: filterDoc}}}], 28650); @@ -64,6 +74,10 @@ load('jstests/aggregation/extras/utils.js'); filterDoc = {input: 'string', as: 'x', cond: true}; assertErrorCode(coll, [{$project: {b: {$filter: filterDoc}}}], 28651); + // 'cond' uses undefined variable name. + filterDoc = {input: '$a', cond: {$eq: [1, '$$var']}}; + assertErrorCode(coll, [{$project: {b: {$filter: filterDoc}}}], 17276); + coll.drop(); assert.writeOK(coll.insert({a: 'string'})); filterDoc = {input: '$a', as: 'x', cond: true}; diff --git a/jstests/aggregation/bugs/server9841.js b/jstests/aggregation/bugs/server9841.js index 28e6037caf1..0f670692adb 100644 --- a/jstests/aggregation/bugs/server9841.js +++ b/jstests/aggregation/bugs/server9841.js @@ -18,6 +18,7 @@ function test(expression, expected) { test({$map: {input: "$simple", as: "var", in : '$$var'}}, [1, 2, 3, 4]); test({$map: {input: "$simple", as: "var", in : {$add: [10, '$$var']}}}, [11, 12, 13, 14]); +test({$map: {input: "$simple", in : '$$this'}}, [1, 2, 3, 4]); test({$map: {input: "$nested", as: "var", in : '$$var.a'}}, [1, 2]); test({$map: {input: "$nested", as: "CURRENT", in : '$a'}}, [1, 2]); @@ -37,5 +38,7 @@ assertErrorCode(t, {$project: {a: {$map: {input: "$notArray", as: "var", in : '$ assertErrorCode( t, {$project: {a: {$map: {x: 1, input: "$simple", as: "var", in : '$$var'}}}}, 16879); assertErrorCode(t, {$project: {a: {$map: {as: "var", in : '$$var'}}}}, 16880); -assertErrorCode(t, {$project: {a: {$map: {input: "$simple", in : '$$var'}}}}, 16881); assertErrorCode(t, {$project: {a: {$map: {input: "$simple", as: "var"}}}}, 16882); + +// 'in' uses undefined variable name. +assertErrorCode(t, {$project: {a: {$map: {input: "$simple", in : '$$var'}}}}, 17276); diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index ad958e837a1..e35adeefe9b 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -1379,7 +1379,6 @@ intrusive_ptr<Expression> ExpressionFilter::parse(BSONElement expr, } uassert(28648, "Missing 'input' parameter to $filter", !inputElem.eoo()); - uassert(28649, "Missing 'as' parameter to $filter", !asElem.eoo()); uassert(28650, "Missing 'cond' parameter to $filter", !condElem.eoo()); // Parse "input", only has outer variables. @@ -1387,7 +1386,10 @@ intrusive_ptr<Expression> ExpressionFilter::parse(BSONElement expr, // Parse "as". VariablesParseState vpsSub(vpsIn); // vpsSub gets our variable, vpsIn doesn't. - string varName = asElem.str(); + + // If "as" is not specified, then use "this" by default. + auto varName = asElem.eoo() ? "this" : asElem.str(); + Variables::uassertValidNameForUserWrite(varName); Variables::Id varId = vpsSub.defineVariable(varName); @@ -1595,7 +1597,6 @@ intrusive_ptr<Expression> ExpressionMap::parse(BSONElement expr, const Variables } uassert(16880, "Missing 'input' parameter to $map", !inputElem.eoo()); - uassert(16881, "Missing 'as' parameter to $map", !asElem.eoo()); uassert(16882, "Missing 'in' parameter to $map", !inElem.eoo()); // parse "input" @@ -1603,7 +1604,10 @@ intrusive_ptr<Expression> ExpressionMap::parse(BSONElement expr, const Variables // parse "as" VariablesParseState vpsSub(vpsIn); // vpsSub gets our vars, vpsIn doesn't. - string varName = asElem.str(); + + // If "as" is not specified, then use "this" by default. + auto varName = asElem.eoo() ? "this" : asElem.str(); + Variables::uassertValidNameForUserWrite(varName); Variables::Id varId = vpsSub.defineVariable(varName); |