diff options
author | Jacob Evans <jacob.evans@mongodb.com> | 2019-11-05 19:45:39 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-11-05 19:45:39 +0000 |
commit | 9561ea73bc0004fc1835430f9789546484c1e7e7 (patch) | |
tree | 926cce8e3ec8fd37e82d24a450f9166001023aa5 /jstests/core | |
parent | 853bdc4b34d9c3505e2af1f443ad7a99a619adea (diff) | |
download | mongo-9561ea73bc0004fc1835430f9789546484c1e7e7.tar.gz |
SERVER-43749 Modernize mapReduce tests in core
Diffstat (limited to 'jstests/core')
-rw-r--r-- | jstests/core/geo_mapreduce.js | 64 | ||||
-rw-r--r-- | jstests/core/geo_mapreduce2.js | 43 | ||||
-rw-r--r-- | jstests/core/mr_killop.js | 220 | ||||
-rw-r--r-- | jstests/core/mr_merge.js | 128 | ||||
-rw-r--r-- | jstests/core/mr_merge2.js | 55 | ||||
-rw-r--r-- | jstests/core/mr_mutable_properties.js | 13 | ||||
-rw-r--r-- | jstests/core/mr_outreduce.js | 65 | ||||
-rw-r--r-- | jstests/core/mr_outreduce2.js | 39 | ||||
-rw-r--r-- | jstests/core/mr_reduce.js | 104 | ||||
-rw-r--r-- | jstests/core/mr_undef.js | 33 |
10 files changed, 294 insertions, 470 deletions
diff --git a/jstests/core/geo_mapreduce.js b/jstests/core/geo_mapreduce.js deleted file mode 100644 index 8bf93d7fd81..00000000000 --- a/jstests/core/geo_mapreduce.js +++ /dev/null @@ -1,64 +0,0 @@ -// @tags: [ -// # mapReduce does not support afterClusterTime. -// does_not_support_causal_consistency, -// does_not_support_stepdowns, -// ] - -// Test script from SERVER-1742 - -// MongoDB test script for mapreduce with geo query - -// setup test collection -db.apples.drop(); -db.apples.insert({"geo": {"lat": 32.68331909, "long": 69.41610718}, "apples": 5}); -db.apples.insert({"geo": {"lat": 35.01860809, "long": 70.92027283}, "apples": 2}); -db.apples.insert({"geo": {"lat": 31.11639023, "long": 64.19970703}, "apples": 11}); -db.apples.insert({"geo": {"lat": 32.64500046, "long": 69.36251068}, "apples": 4}); -db.apples.insert({"geo": {"lat": 33.23638916, "long": 69.81360626}, "apples": 9}); -db.apples.ensureIndex({"geo": "2d"}); - -center = [32.68, 69.41]; -radius = 10 / 111; // 10km; 1 arcdegree ~= 111km -geo_query = { - geo: {'$within': {'$center': [center, radius]}} -}; - -// geo query on collection works fine -res = db.apples.find(geo_query); -assert.eq(2, res.count()); - -// map function -m = function() { - emit(null, {"apples": this.apples}); -}; - -// reduce function -r = function(key, values) { - var total = 0; - for (var i = 0; i < values.length; i++) { - total += values[i].apples; - } - return {"apples": total}; -}; - -// mapreduce without geo query works fine -res = db.apples.mapReduce(m, r, {out: {inline: 1}}); - -printjson(res); -total = res.results[0]; -assert.eq(31, total.value.apples); - -// mapreduce with regular query works fine too -res = db.apples.mapReduce(m, r, {out: {inline: 1}, query: {apples: {'$lt': 9}}}); -total = res.results[0]; -assert.eq(11, total.value.apples); - -// mapreduce with geo query gives error on mongodb version 1.6.2 -// uncaught exception: map reduce failed: { -// "assertion" : "manual matcher config not allowed", -// "assertionCode" : 13285, -// "errmsg" : "db assertion failure", -// "ok" : 0 } -res = db.apples.mapReduce(m, r, {out: {inline: 1}, query: geo_query}); -total = res.results[0]; -assert.eq(9, total.value.apples); diff --git a/jstests/core/geo_mapreduce2.js b/jstests/core/geo_mapreduce2.js deleted file mode 100644 index a740e723101..00000000000 --- a/jstests/core/geo_mapreduce2.js +++ /dev/null @@ -1,43 +0,0 @@ -// @tags: [ -// # mapReduce does not support afterClusterTime. -// does_not_support_causal_consistency, -// does_not_support_stepdowns, -// uses_map_reduce_with_temp_collections, -// ] - -// Geo mapreduce 2 from SERVER-3478 - -var coll = db.geoMR2; -coll.drop(); - -for (var i = 0; i < 300; i++) - coll.insert({i: i, location: [10, 20]}); - -coll.ensureIndex({location: "2d"}); - -// map function -m = function() { - emit(null, {count: this.i}); -}; - -// reduce function -r = function(key, values) { - var total = 0; - for (var i = 0; i < values.length; i++) { - total += values[i].count; - } - - return {count: total}; -}; - -try { - coll.mapReduce(m, r, { - out: coll.getName() + "_mr", - sort: {_id: 1}, - query: {'location': {$within: {$centerSphere: [[10, 20], 0.01]}}} - }); - -} catch (e) { - // This should occur, since we can't in-mem sort for mreduce - printjson(e); -} diff --git a/jstests/core/mr_killop.js b/jstests/core/mr_killop.js index 6c837c52943..07a92e289eb 100644 --- a/jstests/core/mr_killop.js +++ b/jstests/core/mr_killop.js @@ -1,3 +1,4 @@ +// Test killop applied to m/r operations and child ops of m/r operations. // Cannot implicitly shard accessed collections because the "command" field in the currentOp() // output is reported as {"mapreduce.shardedfinish": { mapreduce: "jstests_mr_killop", ... }, ... } // when the "finalize" option to the "mapReduce" command is used on a sharded collection. @@ -9,77 +10,54 @@ // uses_multiple_connections, // uses_map_reduce_with_temp_collections, // ] - -// Test killop applied to m/r operations and child ops of m/r operations. - -t = db.jstests_mr_killop; -t.drop(); -t2 = db.jstests_mr_killop_out; -t2.drop(); -db.adminCommand({"configureFailPoint": 'mr_killop_test_fp', "mode": 'alwaysOn'}); -function debug(x) { - // printjson( x ); -} - -/** @return op code for map reduce op created by spawned shell, or that op's child */ -function op(childLoop) { - p = db.currentOp().inprog; - debug(p); - - let isMapReduce = function(op) { +(function() { +"use strict"; +const source = db.jstests_mr_killop; +source.drop(); +const out = db.jstests_mr_killop_out; +out.drop(); +assert.commandWorked(db.adminCommand({configureFailPoint: "mr_killop_test_fp", mode: "alwaysOn"})); + +/** @return op code for map reduce op created by spawned shell. */ +function getOpCode() { + const inProg = db.currentOp().inprog; + + function isMapReduce(op) { if (!op.command) { return false; } - let cmdBody = op.command; + const cmdBody = op.command; if (cmdBody.$truncated) { - let stringifiedCmd = cmdBody.$truncated; - print('str: ' + tojson(stringifiedCmd)); + const stringifiedCmd = cmdBody.$truncated; return stringifiedCmd.search('mapreduce') >= 0 && - stringifiedCmd.search('jstests_mr_killop') >= 0; + stringifiedCmd.search(source.getName()) >= 0; } - return cmdBody.mapreduce && cmdBody.mapreduce == "jstests_mr_killop"; - }; - - for (var i in p) { - var o = p[i]; - // Identify a map/reduce or where distinct operation by its collection, whether or not - // it is currently active. - if (childLoop) { - if ((o.active || o.waitingForLock) && o.command && o.command.query && - o.command.query.$where && o.command.distinct == "jstests_mr_killop") { - return o.opid; - } - } else { - if ((o.active || o.waitingForLock) && isMapReduce(o)) { - return o.opid; - } - } + return cmdBody.mapreduce && cmdBody.mapreduce == source.getName(); + } + + for (let i in inProg) { + const o = inProg[i]; + // Identify a map/reduce operation by its collection, whether or not it is currently active. + if ((o.active || o.waitingForLock) && isMapReduce(o)) + return o.opid; } return -1; } /** - * Run one map reduce with the specified parameters in a parallel shell, kill the - * map reduce op or its child op with killOp, and wait for the map reduce op to - * terminate. - * @param childLoop - if true, a distinct $where op is killed rather than the map reduce op. - * This is necessay for a child distinct $where of a map reduce op because child - * ops currently mask parent ops in currentOp. + * Run one mapReduce with the specified parameters in a parallel shell. Kill the map reduce op and + * wait for the map reduce op to terminate. */ -function testOne(map, reduce, finalize, scope, childLoop, wait) { - debug("testOne - map = " + tojson(map) + "; reduce = " + tojson(reduce) + - "; finalize = " + tojson(finalize) + "; scope = " + tojson(scope) + - "; childLoop = " + childLoop + "; wait = " + wait); - - t.drop(); - t2.drop(); - // Ensure we have 2 documents for the reduce to run - t.save({a: 1}); - t.save({a: 1}); - - spec = {mapreduce: "jstests_mr_killop", out: "jstests_mr_killop_out", map: map, reduce: reduce}; +function runTest(map, reduce, finalize, scope, wait) { + source.drop(); + out.drop(); + // Ensure we have 2 documents for the reduce to run. + assert.commandWorked(source.insert({a: 1})); + assert.commandWorked(source.insert({a: 1})); + + const spec = {mapreduce: source.getName(), out: out.getName(), map: map, reduce: reduce}; if (finalize) { spec["finalize"] = finalize; } @@ -87,85 +65,94 @@ function testOne(map, reduce, finalize, scope, childLoop, wait) { spec["scope"] = scope; } - // Windows shell strips all double quotes from command line, so use - // single quotes. - stringifiedSpec = tojson(spec).toString().replace(/\n/g, ' ').replace(/\"/g, "\'"); + // Windows shell strips all double quotes from command line, so use single quotes. + const stringifiedSpec = tojson(spec).toString().replace(/\n/g, ' ').replace(/\"/g, "\'"); - // The assert below won't be caught by this test script, but it will cause error messages - // to be printed. - var awaitShell = + // The assert below won't be caught by this test script, but it will cause error messages to be + // printed. + const awaitShell = startParallelShell("assert.commandWorked( db.runCommand( " + stringifiedSpec + " ) );"); if (wait) { sleep(2000); } - o = null; + let opCode = null; assert.soon(function() { - o = op(childLoop); - return o != -1; + opCode = getOpCode(); + return opCode != -1; }); - res = db.killOp(o); - debug("did kill : " + tojson(res)); + db.killOp(opCode); // When the map reduce op is killed, the spawned shell will exit - var exitCode = awaitShell({checkExitSuccess: false}); + const exitCode = awaitShell({checkExitSuccess: false}); assert.neq(0, exitCode, "expected shell to exit abnormally due to map-reduce execution being terminated"); - debug("parallel shell completed"); + assert.eq(-1, getOpCode()); +} - assert.eq(-1, op(childLoop)); +/** Test using wait and non wait modes. */ +function runTests(map, reduce, finalize, scope) { + runTest(map, reduce, finalize, scope, false); + runTest(map, reduce, finalize, scope, true); } -/** Test using wait and non wait modes */ -function test(map, reduce, finalize, scope, childLoop) { - debug(" Non wait mode"); - testOne(map, reduce, finalize, scope, childLoop, false); +/** Test looping in map function. */ +function runMapTests(loop) { + // Without scope. + runTests( + loop, // map + function(k, v) { + return v[0]; + }, // reduce + null, // finalize + null // scope + ); - debug(" Wait mode"); - testOne(map, reduce, finalize, scope, childLoop, true); + // With scope. + runTests( + function() { + loop(); + }, // map + function(k, v) { + return v[0]; + }, // reduce + null, // finalize + {loop: loop} // scope + ); } -/** Test looping in map and reduce functions */ -function runMRTests(loop, childLoop) { - debug(" Running MR test - loop map function. no scope "); - test(loop, // map - function(k, v) { - return v[0]; - }, // reduce - null, // finalize - null, // scope - childLoop); - - debug(" Running MR test - loop reduce function "); - test( +/** Test looping in reduce function. */ +function runReduceTests(loop) { + // Without scope. + runTests( function() { emit(this.a, 1); }, // map loop, // reduce null, // finalize - null, // scope - childLoop); + null // scope + ); - debug(" Running finalization test - loop map function. with scope "); - test( + // With scope. + runTests( function() { - loop(); + emit(this.a, 1); }, // map - function(k, v) { - return v[0]; - }, // reduce - null, // finalize - {loop: loop}, // scope - childLoop); + function() { + loop(); + }, // reduce + null, // finalize + {loop: loop} // scope + ); } -/** Test looping in finalize function */ -function runFinalizeTests(loop, childLoop) { - debug(" Running finalization test - no scope "); - test( +/** Test looping in finalize function. */ +function runFinalizeTests(loop) { + // Without scope. + runTests( function() { emit(this.a, 1); }, // map @@ -173,11 +160,11 @@ function runFinalizeTests(loop, childLoop) { return v[0]; }, // reduce loop, // finalize - null, // scope - childLoop); + null // scope + ); - debug(" Running finalization test - with scope "); - test( + // With scope. + runTests( function() { emit(this.a, 1); }, // map @@ -186,17 +173,18 @@ function runFinalizeTests(loop, childLoop) { }, // reduce function(a, b) { loop(); - }, // finalize - {loop: loop}, // scope - childLoop); + }, // finalize + {loop: loop} // scope + ); } -// Run inside server. No access to debug(). -var loop = function() { +const loop = function() { while (1) { sleep(1000); } }; -runMRTests(loop, false); +runMapTests(loop, false); +runReduceTests(loop, false); runFinalizeTests(loop, false); -db.adminCommand({"configureFailPoint": 'mr_killop_test_fp', "mode": 'off'}); +db.adminCommand({configureFailPoint: "mr_killop_test_fp", mode: "off"}); +}()); diff --git a/jstests/core/mr_merge.js b/jstests/core/mr_merge.js index 835cee55c27..fa9d2c3d873 100644 --- a/jstests/core/mr_merge.js +++ b/jstests/core/mr_merge.js @@ -1,3 +1,4 @@ +// Tests the 'merge' output mode for mapReduce. // Cannot implicitly shard accessed collections because of following errmsg: Cannot output to a // non-sharded collection because sharded collection exists already. // @tags: [ @@ -7,70 +8,97 @@ // does_not_support_stepdowns, // uses_map_reduce_with_temp_collections, // ] +(function() { +"use strict"; +(function() { +const source = db.mr_merge; +source.drop(); -t = db.mr_merge; -t.drop(); +assert.commandWorked(source.insert({_id: 1, a: [1, 2]})); +assert.commandWorked(source.insert({_id: 2, a: [2, 3]})); +assert.commandWorked(source.insert({_id: 3, a: [3, 4]})); -t.insert({a: [1, 2]}); -t.insert({a: [2, 3]}); -t.insert({a: [3, 4]}); - -outName = "mr_merge_out"; -out = db[outName]; +const out = db.mr_merge_out; +const outName = out.getName(); out.drop(); -m = function() { - for (i = 0; i < this.a.length; i++) +const map = function() { + for (let i = 0; i < this.a.length; i++) emit(this.a[i], 1); }; -r = function(k, vs) { +const reduce = function(k, vs) { return Array.sum(vs); }; -function tos(o) { - var s = ""; - for (var i = 0; i < 100; i++) { - if (o[i]) - s += i + "_" + o[i]; - } - return s; -} - -assert.commandWorked(t.mapReduce(m, r, {out: outName})); - -expected = { - "1": 1, - "2": 2, - "3": 2, - "4": 1 -}; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "A"); +assert.commandWorked(source.mapReduce(map, reduce, {out: outName})); + +let expected = [{_id: 1, value: 1}, {_id: 2, value: 2}, {_id: 3, value: 2}, {_id: 4, value: 1}]; +assert.docEq(expected, out.find().sort({_id: 1}).toArray()); + +assert.commandWorked(source.insert({_id: 4, a: [4, 5]})); +// Insert something that should be unaltered by the mapReduce into the output collection. +assert.commandWorked(out.insert({_id: 10, value: 5})); +assert.commandWorked( + source.mapReduce(map, reduce, {out: {merge: outName}, query: {_id: {$gt: 3}}})); + +expected = [ + {_id: 1, value: 1}, + {_id: 2, value: 2}, + {_id: 3, value: 2}, + {_id: 4, value: 1}, + {_id: 5, value: 1}, + {_id: 10, value: 5} +]; +assert.docEq(expected, out.find().sort({_id: 1}).toArray()); -t.insert({a: [4, 5]}); -out.insert({_id: 10, value: "5"}); -assert.commandWorked(t.mapReduce(m, r, {out: outName})); +assert.commandWorked(source.insert({_id: 5, a: [5, 6]})); +// Insert something that should be unaltered by the mapReduce into the output collection. +assert.commandWorked(out.insert({_id: 20, value: 10})); +assert.commandWorked( + source.mapReduce(map, reduce, {out: {merge: outName}, query: {_id: {$gt: 4}}})); -expected["4"]++; -expected["5"] = 1; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "B"); +expected = [ + {_id: 1, value: 1}, + {_id: 2, value: 2}, + {_id: 3, value: 2}, + {_id: 4, value: 1}, + {_id: 5, value: 1}, + {_id: 6, value: 1}, + {_id: 10, value: 5}, + {_id: 20, value: 10} +]; +assert.docEq(expected, out.find().sort({_id: 1}).toArray()); +}()); +(function() { +const source = db.mr_merge; +source.drop(); -t.insert({a: [5, 6]}); -out.insert({_id: 10, value: "5"}); -assert.commandWorked(t.mapReduce(m, r, {out: {merge: outName}})); +assert.commandWorked(source.insert({_id: 1, x: 1})); +assert.commandWorked(source.insert({_id: 2, x: 1})); +assert.commandWorked(source.insert({_id: 3, x: 2})); -expected["5"]++; -expected["10"] = 5; -expected["6"] = 1; +const out = db.mr_merge_out; +const outName = out.getName(); +out.drop(); + +const map = function() { + emit(this.x, 1); +}; +const reduce = function(k, v) { + return Array.sum(v); +}; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "C"); +assert.commandWorked( + source.mapReduce(map, reduce, {out: {merge: outName}, query: {_id: {$gt: 0}}})); -// test that the nonAtomic output gives valid result -t.insert({a: [6, 7]}); -out.insert({_id: 20, value: "10"}); -assert.commandWorked(t.mapReduce(m, r, {out: {merge: outName, nonAtomic: true}})); +assert.eq(2, out.findOne({_id: 1}).value); +assert.eq(1, out.findOne({_id: 2}).value); -expected["6"]++; -expected["20"] = 10; -expected["7"] = 1; +assert.commandWorked(source.insert({_id: 4, x: 2})); +assert.commandWorked( + source.mapReduce(map, reduce, {out: {merge: outName}, query: {_id: {$gt: 3}}})); -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "D"); +assert.eq(2, out.findOne({_id: 1}).value); +assert.eq(1, out.findOne({_id: 2}).value); +}()); +}()); diff --git a/jstests/core/mr_merge2.js b/jstests/core/mr_merge2.js deleted file mode 100644 index df2ada36749..00000000000 --- a/jstests/core/mr_merge2.js +++ /dev/null @@ -1,55 +0,0 @@ -// Cannot implicitly shard accessed collections because of following errmsg: Cannot output to a -// non-sharded collection because sharded collection exists already. -// @tags: [ -// assumes_unsharded_collection, -// # mapReduce does not support afterClusterTime. -// does_not_support_causal_consistency, -// does_not_support_stepdowns, -// uses_map_reduce_with_temp_collections, -// ] -t = db.mr_merge2; -t.drop(); - -t.insert({a: [1, 2]}); -t.insert({a: [2, 3]}); -t.insert({a: [3, 4]}); - -outName = "mr_merge2_out"; -out = db[outName]; -out.drop(); - -m = function() { - for (i = 0; i < this.a.length; i++) - emit(this.a[i], 1); -}; -r = function(k, vs) { - return Array.sum(vs); -}; - -function tos(o) { - var s = ""; - for (var i = 0; i < 100; i++) { - if (o[i]) - s += i + "_" + o[i] + "|"; - } - return s; -} - -outOptions = { - out: {merge: outName} -}; - -res = t.mapReduce(m, r, outOptions); -expected = { - "1": 1, - "2": 2, - "3": 2, - "4": 1 -}; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "A"); - -t.insert({a: [4, 5]}); -res = t.mapReduce(m, r, outOptions); -expected["4"]++; -expected["5"] = 1; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "B"); diff --git a/jstests/core/mr_mutable_properties.js b/jstests/core/mr_mutable_properties.js index d93ab8ce343..0110a7a858c 100644 --- a/jstests/core/mr_mutable_properties.js +++ b/jstests/core/mr_mutable_properties.js @@ -7,11 +7,13 @@ // See SERVER-9448 // Test argument and receiver (aka 'this') objects and their children can be mutated // in Map, Reduce and Finalize functions -var collection = db.mrMutableReceiver; +(function() { +"use strict"; +const collection = db.mrMutableReceiver; collection.drop(); collection.insert({a: 1}); -var map = function() { +const map = function() { // set property on receiver this.feed = {beef: 1}; @@ -21,7 +23,7 @@ var map = function() { emit(this._id, this.a); }; -var reduce = function(key, values) { +const reduce = function(key, values) { // set property on receiver this.feed = {beat: 1}; @@ -39,7 +41,7 @@ var reduce = function(key, values) { return {food: values}; }; -var finalize = function(key, values) { +const finalize = function(key, values) { // set property on receiver this.feed = {ice: 1}; @@ -58,7 +60,7 @@ var finalize = function(key, values) { return values; }; -var mr = collection.mapReduce(map, reduce, {finalize: finalize, out: {inline: 1}}); +const mr = collection.mapReduce(map, reduce, {finalize: finalize, out: {inline: 1}}); printjson(mr); // verify mutated properties exist (order dictated by emit sequence and properties added) @@ -71,3 +73,4 @@ assert.eq(mr.results[0].value.food[5].cream, 1); mr.results[0].value.food.forEach(function(val) { assert.eq(val.mod, 1); }); +}()); diff --git a/jstests/core/mr_outreduce.js b/jstests/core/mr_outreduce.js deleted file mode 100644 index ff9e297a5d2..00000000000 --- a/jstests/core/mr_outreduce.js +++ /dev/null @@ -1,65 +0,0 @@ -// Cannot implicitly shard accessed collections because of following errmsg: Cannot output to a -// non-sharded collection because sharded collection exists already. -// @tags: [ -// assumes_unsharded_collection, -// # mapReduce does not support afterClusterTime. -// does_not_support_causal_consistency, -// does_not_support_stepdowns, -// uses_map_reduce_with_temp_collections, -// ] - -t = db.mr_outreduce; -t.drop(); - -t.insert({_id: 1, a: [1, 2]}); -t.insert({_id: 2, a: [2, 3]}); -t.insert({_id: 3, a: [3, 4]}); - -outName = "mr_outreduce_out"; -out = db[outName]; -out.drop(); - -m = function() { - for (i = 0; i < this.a.length; i++) - emit(this.a[i], 1); -}; -r = function(k, vs) { - return Array.sum(vs); -}; - -function tos(o) { - var s = ""; - for (var i = 0; i < 100; i++) { - if (o[i]) - s += i + "_" + o[i] + "|"; - } - return s; -} - -assert.commandWorked(t.mapReduce(m, r, {out: outName})); - -expected = { - "1": 1, - "2": 2, - "3": 2, - "4": 1 -}; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "A"); - -t.insert({_id: 4, a: [4, 5]}); -out.insert({_id: 10, value: "5"}); // this is a sentinal to make sure it wasn't killed -assert.commandWorked(t.mapReduce(m, r, {out: {reduce: outName}, query: {_id: {$gt: 3}}})); - -expected["4"]++; -expected["5"] = 1; -expected["10"] = 5; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "B"); - -t.insert({_id: 5, a: [5, 6]}); -out.insert({_id: 20, value: "10"}); // this is a sentinal to make sure it wasn't killed -assert.commandWorked(t.mapReduce(m, r, {out: {reduce: outName}, query: {_id: {$gt: 4}}})); - -expected["5"]++; -expected["6"] = 1; -expected["20"] = 10; -assert.eq(tos(expected), tos(out.convertToSingleObject("value")), "C"); diff --git a/jstests/core/mr_outreduce2.js b/jstests/core/mr_outreduce2.js deleted file mode 100644 index a309ad91af8..00000000000 --- a/jstests/core/mr_outreduce2.js +++ /dev/null @@ -1,39 +0,0 @@ -// Cannot implicitly shard accessed collections because of following errmsg: Cannot output to a -// non-sharded collection because sharded collection exists already. -// @tags: [ -// assumes_unsharded_collection, -// # mapReduce does not support afterClusterTime. -// does_not_support_causal_consistency, -// does_not_support_stepdowns, -// uses_map_reduce_with_temp_collections, -// ] - -normal = "mr_outreduce2"; -out = normal + "_out"; - -t = db[normal]; -t.drop(); - -db[out].drop(); - -t.insert({_id: 1, x: 1}); -t.insert({_id: 2, x: 1}); -t.insert({_id: 3, x: 2}); - -m = function() { - emit(this.x, 1); -}; -r = function(k, v) { - return Array.sum(v); -}; - -res = t.mapReduce(m, r, {out: {reduce: out}, query: {_id: {$gt: 0}}}); - -assert.eq(2, db[out].findOne({_id: 1}).value, "A1"); -assert.eq(1, db[out].findOne({_id: 2}).value, "A2"); - -t.insert({_id: 4, x: 2}); -res = t.mapReduce(m, r, {out: {reduce: out}, query: {_id: {$gt: 3}}}); - -assert.eq(2, db[out].findOne({_id: 1}).value, "B1"); -assert.eq(2, db[out].findOne({_id: 2}).value, "B2"); diff --git a/jstests/core/mr_reduce.js b/jstests/core/mr_reduce.js new file mode 100644 index 00000000000..aded1cf471d --- /dev/null +++ b/jstests/core/mr_reduce.js @@ -0,0 +1,104 @@ +// Tests the 'reduce' output mode for mapReduce. +// Cannot implicitly shard accessed collections because of following errmsg: Cannot output to a +// non-sharded collection because sharded collection exists already. +// @tags: [ +// assumes_unsharded_collection, +// # mapReduce does not support afterClusterTime. +// does_not_support_causal_consistency, +// does_not_support_stepdowns, +// uses_map_reduce_with_temp_collections, +// ] +(function() { +"use strict"; +(function() { +const source = db.mr_reduce; +source.drop(); + +assert.commandWorked(source.insert({_id: 1, a: [1, 2]})); +assert.commandWorked(source.insert({_id: 2, a: [2, 3]})); +assert.commandWorked(source.insert({_id: 3, a: [3, 4]})); + +const out = db.mr_reduce_out; +const outName = out.getName(); +out.drop(); + +const map = function() { + for (let i = 0; i < this.a.length; i++) + emit(this.a[i], 1); +}; +const reduce = function(k, vs) { + return Array.sum(vs); +}; + +assert.commandWorked(source.mapReduce(map, reduce, {out: outName})); + +let expected = [{_id: 1, value: 1}, {_id: 2, value: 2}, {_id: 3, value: 2}, {_id: 4, value: 1}]; +assert.docEq(expected, out.find().sort({_id: 1}).toArray()); + +assert.commandWorked(source.insert({_id: 4, a: [4, 5]})); +// Insert something that should be unaltered by the mapReduce into the output collection. +assert.commandWorked(out.insert({_id: 10, value: 5})); +assert.commandWorked( + source.mapReduce(map, reduce, {out: {reduce: outName}, query: {_id: {$gt: 3}}})); + +expected = [ + {_id: 1, value: 1}, + {_id: 2, value: 2}, + {_id: 3, value: 2}, + {_id: 4, value: 2}, + {_id: 5, value: 1}, + {_id: 10, value: 5} +]; +assert.docEq(expected, out.find().sort({_id: 1}).toArray()); + +assert.commandWorked(source.insert({_id: 5, a: [5, 6]})); +// Insert something that should be unaltered by the mapReduce into the output collection. +assert.commandWorked(out.insert({_id: 20, value: 10})); +assert.commandWorked( + source.mapReduce(map, reduce, {out: {reduce: outName}, query: {_id: {$gt: 4}}})); + +expected = [ + {_id: 1, value: 1}, + {_id: 2, value: 2}, + {_id: 3, value: 2}, + {_id: 4, value: 2}, + {_id: 5, value: 2}, + {_id: 6, value: 1}, + {_id: 10, value: 5}, + {_id: 20, value: 10} +]; +assert.docEq(expected, out.find().sort({_id: 1}).toArray()); +}()); +(function() { +const source = db.mr_reduce; +source.drop(); + +assert.commandWorked(source.insert({_id: 1, x: 1})); +assert.commandWorked(source.insert({_id: 2, x: 1})); +assert.commandWorked(source.insert({_id: 3, x: 2})); + +const out = db.mr_reduce_out; +const outName = out.getName(); +out.drop(); + +const map = function() { + emit(this.x, 1); +}; +const reduce = function(k, v) { + return Array.sum(v); +}; + +assert.commandWorked( + source.mapReduce(map, reduce, {out: {reduce: outName}, query: {_id: {$gt: 0}}})); + +assert.eq(2, out.findOne({_id: 1}).value); +assert.eq(1, out.findOne({_id: 2}).value); + +assert.commandWorked(source.insert({_id: 4, x: 2})); +assert.commandWorked( + source.mapReduce(map, reduce, {out: {reduce: outName}, query: {_id: {$gt: 3}}})); + +assert.eq(2, out.findOne({_id: 1}).value); +assert.eq(2, out.findOne({_id: 2}).value); +}()); +}()); diff --git a/jstests/core/mr_undef.js b/jstests/core/mr_undef.js deleted file mode 100644 index 5754a1c3084..00000000000 --- a/jstests/core/mr_undef.js +++ /dev/null @@ -1,33 +0,0 @@ -// @tags: [ -// # mapReduce does not support afterClusterTime. -// does_not_support_causal_consistency, -// does_not_support_stepdowns, -// uses_map_reduce_with_temp_collections, -// ] -t = db.mr_undef; -t.drop(); - -outname = "mr_undef_out"; -out = db[outname]; -out.drop(); - -t.insert({x: 0}); - -var m = function() { - emit(this.mod, this.x); -}; -var r = function(k, v) { - total = 0; - for (i in v) { - total += v[i]; - } - return total; -}; - -res = t.mapReduce(m, r, {out: outname}); - -assert.eq(0, out.find({_id: {$type: 6}}).itcount(), "A1"); -assert.eq(1, out.find({_id: {$type: 10}}).itcount(), "A2"); - -x = out.findOne(); -assert.eq(x, out.findOne({_id: x["_id"]}), "A3"); |