diff options
Diffstat (limited to 'jstests/aggregation/bugs/server19095.js')
-rw-r--r-- | jstests/aggregation/bugs/server19095.js | 387 |
1 files changed, 147 insertions, 240 deletions
diff --git a/jstests/aggregation/bugs/server19095.js b/jstests/aggregation/bugs/server19095.js index 3728c06c06b..7d023ebc271 100644 --- a/jstests/aggregation/bugs/server19095.js +++ b/jstests/aggregation/bugs/server19095.js @@ -8,23 +8,23 @@ load("jstests/aggregation/extras/utils.js"); // Used by testPipeline to sort result documents. All _ids must be primitives. function compareId(a, b) { - if (a._id < b._id) { - return -1; - } - if (a._id > b._id) { - return 1; - } - return 0; + if (a._id < b._id) { + return -1; + } + if (a._id > b._id) { + return 1; + } + return 0; } // Helper for testing that pipeline returns correct set of results. function testPipeline(pipeline, expectedResult, collection) { assert.eq(collection.aggregate(pipeline).toArray().sort(compareId), - expectedResult.sort(compareId)); + expectedResult.sort(compareId)); } function runTest(coll, from) { - var db = null; // Using the db variable is banned in this function. + var db = null; // Using the db variable is banned in this function. assert.writeOK(coll.insert({_id: 0, a: 1})); assert.writeOK(coll.insert({_id: 1, a: null})); @@ -45,14 +45,9 @@ load("jstests/aggregation/extras/utils.js"); {_id: 1, a: null, "same": [{_id: 1, b: null}, {_id: 2}]}, {_id: 2, "same": [{_id: 1, b: null}, {_id: 2}]} ]; - testPipeline([{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "same" - } - }], expectedResults, coll); + testPipeline([{$lookup: {localField: "a", foreignField: "b", from: "from", as: "same"}}], + expectedResults, + coll); // If localField is nonexistent, it is treated as if it is null. expectedResults = [ @@ -61,13 +56,10 @@ load("jstests/aggregation/extras/utils.js"); {_id: 2, "same": [{_id: 1, b: null}, {_id: 2}]} ]; testPipeline([{ - $lookup: { - localField: "nonexistent", - foreignField: "b", - from: "from", - as: "same" - } - }], expectedResults, coll); + $lookup: {localField: "nonexistent", foreignField: "b", from: "from", as: "same"} + }], + expectedResults, + coll); // If foreignField is nonexistent, it is treated as if it is null. expectedResults = [ @@ -76,36 +68,24 @@ load("jstests/aggregation/extras/utils.js"); {_id: 2, "same": [{_id: 0, b: 1}, {_id: 1, b: null}, {_id: 2}]} ]; testPipeline([{ - $lookup: { - localField: "a", - foreignField: "nonexistent", - from: "from", - as: "same" - } - }], expectedResults, coll); + $lookup: {localField: "a", foreignField: "nonexistent", from: "from", as: "same"} + }], + expectedResults, + coll); // If there are no matches or the from coll doesn't exist, the result is an empty array. - expectedResults = [ - {_id: 0, a: 1, "same": []}, - {_id: 1, a: null, "same": []}, - {_id: 2, "same": []} - ]; + expectedResults = + [{_id: 0, a: 1, "same": []}, {_id: 1, a: null, "same": []}, {_id: 2, "same": []}]; testPipeline([{ - $lookup: { - localField: "_id", - foreignField: "nonexistent", - from: "from", - as: "same" - } - }], expectedResults, coll); + $lookup: {localField: "_id", foreignField: "nonexistent", from: "from", as: "same"} + }], + expectedResults, + coll); testPipeline([{ - $lookup: { - localField: "a", - foreignField: "b", - from: "nonexistent", - as: "same" - } - }], expectedResults, coll); + $lookup: {localField: "a", foreignField: "b", from: "nonexistent", as: "same"} + }], + expectedResults, + coll); // If field name specified by "as" already exists, it is overwritten. expectedResults = [ @@ -113,42 +93,26 @@ load("jstests/aggregation/extras/utils.js"); {_id: 1, "a": [{_id: 1, b: null}, {_id: 2}]}, {_id: 2, "a": [{_id: 1, b: null}, {_id: 2}]} ]; - testPipeline([{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "a" - } - }], expectedResults, coll); - + testPipeline([{$lookup: {localField: "a", foreignField: "b", from: "from", as: "a"}}], + expectedResults, + coll); // Running multiple $lookups in the same pipeline is allowed. expectedResults = [ - {_id: 0, a: 1, "c": [{_id:0, b:1}], "d": [{_id:0, b:1}]}, - {_id: 1, a: null, "c": [{_id:1, b:null}, {_id:2}], "d": [{_id:1, b:null}, {_id:2}]}, - {_id: 2, "c": [{_id:1, b:null}, {_id:2}], "d": [{_id:1, b:null}, {_id:2}]} + {_id: 0, a: 1, "c": [{_id: 0, b: 1}], "d": [{_id: 0, b: 1}]}, + { + _id: 1, + a: null, "c": [{_id: 1, b: null}, {_id: 2}], "d": [{_id: 1, b: null}, {_id: 2}] + }, + {_id: 2, "c": [{_id: 1, b: null}, {_id: 2}], "d": [{_id: 1, b: null}, {_id: 2}]} ]; - testPipeline([{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "c" - } - }, { - $project: { - "a": 1, - "c": 1 - } - }, { - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "d" - } - }], expectedResults, coll); + testPipeline([ + {$lookup: {localField: "a", foreignField: "b", from: "from", as: "c"}}, + {$project: {"a": 1, "c": 1}}, + {$lookup: {localField: "a", foreignField: "b", from: "from", as: "d"}} + ], + expectedResults, + coll); // // Coalescing with $unwind. @@ -162,16 +126,12 @@ load("jstests/aggregation/extras/utils.js"); {_id: 2, same: {_id: 1, b: null}}, {_id: 2, same: {_id: 2}} ]; - testPipeline([{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "same" - } - }, { - $unwind: {path: "$same"} - }], expectedResults, coll); + testPipeline([ + {$lookup: {localField: "a", foreignField: "b", from: "from", as: "same"}}, + {$unwind: {path: "$same"}} + ], + expectedResults, + coll); // An $unwind on the "as" field, with includeArrayIndex. expectedResults = [ @@ -181,72 +141,39 @@ load("jstests/aggregation/extras/utils.js"); {_id: 2, same: {_id: 1, b: null}, index: NumberLong(0)}, {_id: 2, same: {_id: 2}, index: NumberLong(1)}, ]; - testPipeline([{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "same" - } - }, { - $unwind: { - path: "$same", - includeArrayIndex: "index" - } - }], expectedResults, coll); + testPipeline([ + {$lookup: {localField: "a", foreignField: "b", from: "from", as: "same"}}, + {$unwind: {path: "$same", includeArrayIndex: "index"}} + ], + expectedResults, + coll); // Normal $unwind with no matching documents. expectedResults = []; - testPipeline([{ - $lookup: { - localField: "_id", - foreignField: "nonexistent", - from: "from", - as: "same" - } - }, { - $unwind: {path: "$same"} - }], expectedResults, coll); + testPipeline([ + {$lookup: {localField: "_id", foreignField: "nonexistent", from: "from", as: "same"}}, + {$unwind: {path: "$same"}} + ], + expectedResults, + coll); // $unwind with preserveNullAndEmptyArray with no matching documents. - expectedResults = [ - {_id: 0, a: 1}, - {_id: 1, a: null}, - {_id: 2}, - ]; - testPipeline([{ - $lookup: { - localField: "_id", - foreignField: "nonexistent", - from: "from", - as: "same" - } - }, { - $unwind: { - path: "$same", - preserveNullAndEmptyArrays: true - } - }], expectedResults, coll); + expectedResults = [{_id: 0, a: 1}, {_id: 1, a: null}, {_id: 2}, ]; + testPipeline([ + {$lookup: {localField: "_id", foreignField: "nonexistent", from: "from", as: "same"}}, + {$unwind: {path: "$same", preserveNullAndEmptyArrays: true}} + ], + expectedResults, + coll); // $unwind with preserveNullAndEmptyArray, some with matching documents, some without. - expectedResults = [ - {_id: 0, a: 1}, - {_id: 1, a: null, same: {_id: 0, b: 1}}, - {_id: 2}, - ]; - testPipeline([{ - $lookup: { - localField: "_id", - foreignField: "b", - from: "from", - as: "same" - } - }, { - $unwind: { - path: "$same", - preserveNullAndEmptyArrays: true - } - }], expectedResults, coll); + expectedResults = [{_id: 0, a: 1}, {_id: 1, a: null, same: {_id: 0, b: 1}}, {_id: 2}, ]; + testPipeline([ + {$lookup: {localField: "_id", foreignField: "b", from: "from", as: "same"}}, + {$unwind: {path: "$same", preserveNullAndEmptyArrays: true}} + ], + expectedResults, + coll); // $unwind with preserveNullAndEmptyArray and includeArrayIndex, some with matching // documents, some without. @@ -255,20 +182,15 @@ load("jstests/aggregation/extras/utils.js"); {_id: 1, a: null, same: {_id: 0, b: 1}, index: NumberLong(0)}, {_id: 2, index: null}, ]; - testPipeline([{ - $lookup: { - localField: "_id", - foreignField: "b", - from: "from", - as: "same" + testPipeline([ + {$lookup: {localField: "_id", foreignField: "b", from: "from", as: "same"}}, + { + $unwind: + {path: "$same", preserveNullAndEmptyArrays: true, includeArrayIndex: "index"} } - }, { - $unwind: { - path: "$same", - preserveNullAndEmptyArrays: true, - includeArrayIndex: "index" - } - }], expectedResults, coll); + ], + expectedResults, + coll); // // Dependencies. @@ -281,18 +203,12 @@ load("jstests/aggregation/extras/utils.js"); {_id: 1, "same": [{_id: 1, b: null}, {_id: 2}]}, {_id: 2, "same": [{_id: 1, b: null}, {_id: 2}]} ]; - testPipeline([{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "same" - } - }, { - $project: { - "same": 1 - } - }], expectedResults, coll); + testPipeline([ + {$lookup: {localField: "a", foreignField: "b", from: "from", as: "same"}}, + {$project: {"same": 1}} + ], + expectedResults, + coll); // // Dotted field paths. @@ -312,14 +228,7 @@ load("jstests/aggregation/extras/utils.js"); assert.writeOK(from.insert({_id: 4, b: {c: 2}})); // Once without a dotted field. - var pipeline = [{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "same" - } - }]; + var pipeline = [{$lookup: {localField: "a", foreignField: "b", from: "from", as: "same"}}]; expectedResults = [ {_id: 0, a: 1, "same": [{_id: 0, b: 1}]}, {_id: 1, a: null, "same": [{_id: 1, b: null}, {_id: 2}]}, @@ -329,14 +238,7 @@ load("jstests/aggregation/extras/utils.js"); testPipeline(pipeline, expectedResults, coll); // Look up a dotted field. - pipeline = [{ - $lookup: { - localField: "a.c", - foreignField: "b.c", - from: "from", - as: "same" - } - }]; + pipeline = [{$lookup: {localField: "a.c", foreignField: "b.c", from: "from", as: "same"}}]; // All but the last document in 'coll' have a nullish value for 'a.c'. expectedResults = [ {_id: 0, a: 1, same: [{_id: 0, b: 1}, {_id: 1, b: null}, {_id: 2}]}, @@ -354,25 +256,33 @@ load("jstests/aggregation/extras/utils.js"); from.drop(); assert.writeOK(from.insert({_id: 0, target: 1})); - pipeline = [{ - $lookup: { - localField: "a.b", - foreignField: "target", - from: "from", - as: "same.documents", - } - }, { - // Expected input to $unwind: - // {_id: 0, a: {b: 1}, same: {documents: [{_id: 0, target: 1}]}} - // {_id: 1, same: {documents: []}} - $unwind: { - path: "$same.documents", - preserveNullAndEmptyArrays: true, - includeArrayIndex: "c.d.e", + pipeline = [ + { + $lookup: { + localField: "a.b", + foreignField: "target", + from: "from", + as: "same.documents", + } + }, + { + // Expected input to $unwind: + // {_id: 0, a: {b: 1}, same: {documents: [{_id: 0, target: 1}]}} + // {_id: 1, same: {documents: []}} + $unwind: { + path: "$same.documents", + preserveNullAndEmptyArrays: true, + includeArrayIndex: "c.d.e", + } } - }]; + ]; expectedResults = [ - {_id: 0, a: {b: 1}, same: {documents: {_id: 0, target: 1}}, c: {d: {e: NumberLong(0)}}}, + { + _id: 0, + a: {b: 1}, + same: {documents: {_id: 0, target: 1}}, + c: {d: {e: NumberLong(0)}} + }, {_id: 1, same: {}, c: {d: {e: null}}}, ]; testPipeline(pipeline, expectedResults, coll); @@ -390,16 +300,16 @@ load("jstests/aggregation/extras/utils.js"); assert.writeOK(from.insert({_id: 1, b: "string that matches /a regex/"})); pipeline = [ - {$lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "b", - }}, - ]; - expectedResults = [ - {_id: 0, a: /a regex/, b: [{_id: 0, b: /a regex/}]} + { + $lookup: { + localField: "a", + foreignField: "b", + from: "from", + as: "b", + } + }, ]; + expectedResults = [{_id: 0, a: /a regex/, b: [{_id: 0, b: /a regex/}]}]; testPipeline(pipeline, expectedResults, coll); // @@ -407,20 +317,21 @@ load("jstests/aggregation/extras/utils.js"); // // All four fields must be specified. - assertErrorCode(coll, [{$lookup: {foreignField:"b", from:"from", as:"same"}}], 4572); - assertErrorCode(coll, [{$lookup: {localField:"a", from:"from", as:"same"}}], 4572); - assertErrorCode(coll, [{$lookup: {localField:"a", foreignField:"b", as:"same"}}], 4572); - assertErrorCode(coll, [{$lookup: {localField:"a", foreignField:"b", from:"from"}}], 4572); + assertErrorCode(coll, [{$lookup: {foreignField: "b", from: "from", as: "same"}}], 4572); + assertErrorCode(coll, [{$lookup: {localField: "a", from: "from", as: "same"}}], 4572); + assertErrorCode(coll, [{$lookup: {localField: "a", foreignField: "b", as: "same"}}], 4572); + assertErrorCode( + coll, [{$lookup: {localField: "a", foreignField: "b", from: "from"}}], 4572); // All four field's values must be strings. - assertErrorCode(coll, [{$lookup: {localField:1, foreignField:"b", from:"from", as:"as"}}] - , 4570); - assertErrorCode(coll, [{$lookup: {localField:"a", foreignField:1, from:"from", as:"as"}}] - , 4570); - assertErrorCode(coll, [{$lookup: {localField:"a", foreignField:"b", from:1, as:"as"}}] - , 4570); - assertErrorCode(coll, [{$lookup: {localField:"a", foreignField: "b", from:"from", as:1}}] - , 4570); + assertErrorCode( + coll, [{$lookup: {localField: 1, foreignField: "b", from: "from", as: "as"}}], 4570); + assertErrorCode( + coll, [{$lookup: {localField: "a", foreignField: 1, from: "from", as: "as"}}], 4570); + assertErrorCode( + coll, [{$lookup: {localField: "a", foreignField: "b", from: 1, as: "as"}}], 4570); + assertErrorCode( + coll, [{$lookup: {localField: "a", foreignField: "b", from: "from", as: 1}}], 4570); // $lookup's field must be an object. assertErrorCode(coll, [{$lookup: "string"}], 4569); @@ -433,21 +344,17 @@ load("jstests/aggregation/extras/utils.js"); // Run tests in a sharded environment. var sharded = new ShardingTest({shards: 2, mongos: 1}); - assert(sharded.adminCommand({enableSharding : "test"})); + assert(sharded.adminCommand({enableSharding: "test"})); sharded.getDB('test').lookUp.drop(); sharded.getDB('test').from.drop(); assert(sharded.adminCommand({shardCollection: "test.lookUp", key: {_id: 'hashed'}})); runTest(sharded.getDB('test').lookUp, sharded.getDB('test').from); // An error is thrown if the from collection is sharded. - assert(sharded.adminCommand({ shardCollection:"test.from", key: {_id: 1}})); - assertErrorCode(sharded.getDB('test').lookUp, [{ - $lookup: { - localField: "a", - foreignField: "b", - from: "from", - as: "same" - } - }], 28769); + assert(sharded.adminCommand({shardCollection: "test.from", key: {_id: 1}})); + assertErrorCode( + sharded.getDB('test').lookUp, + [{$lookup: {localField: "a", foreignField: "b", from: "from", as: "same"}}], + 28769); sharded.stop(); }()); |