diff options
author | Charlie Swanson <charlie.swanson@mongodb.com> | 2019-10-01 19:53:39 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-10-01 19:53:39 +0000 |
commit | 94545ee7be121f6bf31696d9f14edf4ebc62adf4 (patch) | |
tree | 60f1cfada19be2e76ee084400c487a69330ce32a | |
parent | 6d0a0e46b987dbc69a5694ff03d53d7e7e25b065 (diff) | |
download | mongo-94545ee7be121f6bf31696d9f14edf4ebc62adf4.tar.gz |
SERVER-43304 Modernize mr1.js
This reverts commit be1be55d991f7bed4d3896f5be53afbb4e579729.
12 files changed, 206 insertions, 213 deletions
diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml index 66bb144b1e8..40c941c36b0 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_100ms_refresh_jscore_passthrough.yml @@ -91,7 +91,7 @@ selector: - jstests/core/sort_array.js # TODO: SERVER-16605 - jstests/core/mr_index.js - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js - jstests/core/mr5.js diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml index 4c8be72d6d8..6a5c3202daf 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_10sec_refresh_jscore_passthrough.yml @@ -91,7 +91,7 @@ selector: - jstests/core/sort_array.js # TODO: SERVER-16605 - jstests/core/mr_index.js - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js - jstests/core/mr5.js diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml index b102942e52c..a75bc546375 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_1sec_refresh_jscore_passthrough.yml @@ -91,7 +91,7 @@ selector: - jstests/core/sort_array.js # TODO: SERVER-16605 - jstests/core/mr_index.js - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js - jstests/core/mr5.js diff --git a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml index 89ea274bd8b..4ec3bf5be73 100644 --- a/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/logical_session_cache_sharding_default_refresh_jscore_passthrough.yml @@ -91,7 +91,7 @@ selector: - jstests/core/sort_array.js # TODO: SERVER-16605 - jstests/core/mr_index.js - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js - jstests/core/mr5.js diff --git a/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml index 1072d1c9570..50ec6ff4690 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_local_read_write_multi_stmt_txn_jscore_passthrough.yml @@ -85,7 +85,7 @@ selector: - jstests/core/optimized_match_explain.js - jstests/core/sort_array.js # TODO: SERVER-16605 MapReduce into sharded collection with hashed index fails - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml index 2593d8ffc0b..207f84cd928 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_jscore_passthrough.yml @@ -85,7 +85,7 @@ selector: - jstests/core/optimized_match_explain.js - jstests/core/sort_array.js # TODO: SERVER-16605 MapReduce into sharded collection with hashed index fails - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml index 5a154c63cc4..b1983e9082f 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_kill_primary_jscore_passthrough.yml @@ -85,7 +85,7 @@ selector: - jstests/core/optimized_match_explain.js - jstests/core/sort_array.js # TODO: SERVER-16605 MapReduce into sharded collection with hashed index fails - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js diff --git a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml index 2cca2cfbcdd..8850efcc8d0 100644 --- a/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/multi_shard_multi_stmt_txn_stepdown_primary_jscore_passthrough.yml @@ -85,7 +85,7 @@ selector: - jstests/core/optimized_match_explain.js - jstests/core/sort_array.js # TODO: SERVER-16605 MapReduce into sharded collection with hashed index fails - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js diff --git a/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml b/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml index f3a6c31672b..fd2921b5ef7 100644 --- a/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml +++ b/buildscripts/resmokeconfig/suites/multi_stmt_txn_jscore_passthrough_with_migration.yml @@ -85,7 +85,7 @@ selector: - jstests/core/optimized_match_explain.js - jstests/core/sort_array.js # TODO: SERVER-16605 MapReduce into sharded collection with hashed index fails - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js # Create index command arbitrarily picks one of the errors if there are multiple errors from the diff --git a/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml index 8cee5e28e21..30a3f185a2a 100644 --- a/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml +++ b/buildscripts/resmokeconfig/suites/sharded_causally_consistent_jscore_passthrough.yml @@ -63,7 +63,7 @@ selector: # collection is sharded on anything other than {_id: 1}. - jstests/core/mr_undef.js # TODO: SERVER-16605 - - jstests/core/mr1.js + - jstests/core/mr_correctness.js - jstests/core/mr3.js - jstests/core/mr4.js # TODO: SERVER-30052 diff --git a/jstests/core/mr1.js b/jstests/core/mr1.js deleted file mode 100644 index d43b6b8303a..00000000000 --- a/jstests/core/mr1.js +++ /dev/null @@ -1,203 +0,0 @@ -// @tags: [ -// # mapReduce does not support afterClusterTime. -// does_not_support_causal_consistency, -// does_not_support_stepdowns, -// requires_fastcount, -// requires_getmore, -// uses_map_reduce_with_temp_collections, -// ] - -t = db.mr1; -t.drop(); - -t.save({x: 1, tags: ["a", "b"]}); -t.save({x: 2, tags: ["b", "c"]}); -t.save({x: 3, tags: ["c", "a"]}); -t.save({x: 4, tags: ["b", "c"]}); - -emit = printjson; - -function d(x) { - printjson(x); -} - -ks = "_id"; -if (db.version() == "1.1.1") - ks = "key"; - -m = function() { - this.tags.forEach(function(z) { - emit(z, {count: 1}); - }); -}; - -m2 = function() { - for (var i = 0; i < this.tags.length; i++) { - emit(this.tags[i], 1); - } -}; - -r = function(key, values) { - var total = 0; - for (var i = 0; i < values.length; i++) { - total += values[i].count; - } - return {count: total}; -}; - -r2 = function(key, values) { - var total = 0; - for (var i = 0; i < values.length; i++) { - total += values[i]; - } - return total; -}; - -res = db.runCommand({mapreduce: "mr1", map: m, reduce: r, out: "mr1_out"}); -d(res); -if (ks == "_id") - assert(res.ok, "not ok"); -assert.eq(4, res.counts.input, "A"); -x = db[res.result]; - -assert.eq(3, x.find().count(), "B"); -x.find().forEach(d); -z = {}; -x.find().forEach(function(a) { - z[a[ks]] = a.value.count; -}); -d(z); -assert.eq(3, Object.keySet(z).length, "C"); -assert.eq(2, z.a, "D"); -assert.eq(3, z.b, "E"); -assert.eq(3, z.c, "F"); -x.drop(); - -res = db.runCommand({mapreduce: "mr1", map: m, reduce: r, query: {x: {"$gt": 2}}, out: "mr1_out"}); -d(res); -assert.eq(2, res.counts.input, "B"); -x = db[res.result]; -z = {}; -x.find().forEach(function(a) { - z[a[ks]] = a.value.count; -}); -assert.eq(1, z.a, "C1"); -assert.eq(1, z.b, "C2"); -assert.eq(2, z.c, "C3"); -x.drop(); - -res = - db.runCommand({mapreduce: "mr1", map: m2, reduce: r2, query: {x: {"$gt": 2}}, out: "mr1_out"}); -d(res); -assert.eq(2, res.counts.input, "B"); -x = db[res.result]; -z = {}; -x.find().forEach(function(a) { - z[a[ks]] = a.value; -}); -assert.eq(1, z.a, "C1z"); -assert.eq(1, z.b, "C2z"); -assert.eq(2, z.c, "C3z"); -x.drop(); - -res = db.runCommand({mapreduce: "mr1", out: "mr1_foo", map: m, reduce: r, query: {x: {"$gt": 2}}}); -d(res); -assert.eq(2, res.counts.input, "B2"); -assert.eq("mr1_foo", res.result, "B2-c"); -x = db[res.result]; -z = {}; -x.find().forEach(function(a) { - z[a[ks]] = a.value.count; -}); -assert.eq(1, z.a, "C1a"); -assert.eq(1, z.b, "C2a"); -assert.eq(2, z.c, "C3a"); -x.drop(); - -for (i = 5; i < 1000; i++) { - t.save({x: i, tags: ["b", "d"]}); -} - -res = db.runCommand({mapreduce: "mr1", map: m, reduce: r, out: "mr1_out"}); -d(res); -assert.eq(999, res.counts.input, "Z1"); -x = db[res.result]; -x.find().forEach(d); -assert.eq(4, x.find().count(), "Z2"); -assert.eq("a,b,c,d", x.distinct(ks), "Z3"); - -function getk(k) { - var o = {}; - o[ks] = k; - return x.findOne(o); -} - -assert.eq(2, getk("a").value.count, "ZA"); -assert.eq(998, getk("b").value.count, "ZB"); -assert.eq(3, getk("c").value.count, "ZC"); -assert.eq(995, getk("d").value.count, "ZD"); -x.drop(); - -if (true) { - printjson(db.runCommand({mapreduce: "mr1", map: m, reduce: r, verbose: true, out: "mr1_out"})); -} - -print("t1: " + Date.timeFunc(function() { - var out = db.runCommand({mapreduce: "mr1", map: m, reduce: r, out: "mr1_out"}); - if (ks == "_id") - assert(out.ok, "XXX : " + tojson(out)); - db[out.result].drop(); -}, 10) + " (~500 on 2.8ghz) - itcount: " + Date.timeFunc(function() { - db.mr1.find().itcount(); -}, 10)); - -// test doesn't exist -res = - db.runCommand({mapreduce: "lasjdlasjdlasjdjasldjalsdj12e", map: m, reduce: r, out: "mr1_out"}); -assert(!res.ok, "should be not ok"); - -if (true) { - correct = {}; - - var bulk = t.initializeUnorderedBulkOp(); - for (i = 0; i < 20000; i++) { - k = "Z" + i % 10000; - if (correct[k]) - correct[k]++; - else - correct[k] = 1; - bulk.insert({x: i, tags: [k]}); - } - assert.commandWorked(bulk.execute()); - - res = db.runCommand({mapreduce: "mr1", out: "mr1_foo", map: m, reduce: r}); - d(res); - print("t2: " + res.timeMillis + " (~3500 on 2.8ghz) - itcount: " + Date.timeFunc(function() { - db.mr1.find().itcount(); - })); - x = db[res.result]; - z = {}; - x.find().forEach(function(a) { - z[a[ks]] = a.value.count; - }); - for (zz in z) { - if (zz.indexOf("Z") == 0) { - assert.eq(correct[zz], z[zz], "ZZ : " + zz); - } - } - x.drop(); - - res = db.runCommand({mapreduce: "mr1", out: "mr1_out", map: m2, reduce: r2}); - d(res); - print("t3: " + res.timeMillis + " (~3500 on 2.8ghz)"); - - res = db.runCommand({mapreduce: "mr1", map: m2, reduce: r2, out: {inline: true}}); - print("t4: " + res.timeMillis); -} - -res = db.runCommand({mapreduce: "mr1", map: m, reduce: r, out: "mr1_out"}); -assert(res.ok, "should be ok"); - -t.drop(); -t1 = db.mr1_out; -t1.drop(); diff --git a/jstests/core/mr_correctness.js b/jstests/core/mr_correctness.js new file mode 100644 index 00000000000..466e5bc1b32 --- /dev/null +++ b/jstests/core/mr_correctness.js @@ -0,0 +1,196 @@ +// Basic correctness tests for the mapReduce command. +// @tags: [ +// # mapReduce does not support afterClusterTime. +// does_not_support_causal_consistency, +// does_not_support_stepdowns, +// requires_fastcount, +// requires_getmore, +// uses_map_reduce_with_temp_collections, +// ] +(function() { +"use strict"; +load("jstests/libs/fixture_helpers.js"); // For "FixtureHelpers". + +const coll = db.mr_correctness; +coll.drop(); + +assert.commandWorked(coll.insert({x: 1, tags: ["a", "b"]})); +assert.commandWorked(coll.insert({x: 2, tags: ["b", "c"]})); +assert.commandWorked(coll.insert({x: 3, tags: ["c", "a"]})); +assert.commandWorked(coll.insert({x: 4, tags: ["b", "c"]})); + +function mapToObj() { + this.tags.forEach(function(z) { + emit(z, {count: 1}); + }); +} + +function reduceObjs(key, values) { + let total = 0; + for (let i = 0; i < values.length; i++) { + total += values[i].count; + } + return {count: total}; +} + +const outColl = db[coll.getName() + "_out"]; +outColl.drop(); +(function testBasicMapReduce() { + const res = db.runCommand( + {mapReduce: coll.getName(), map: mapToObj, reduce: reduceObjs, out: outColl.getName()}); + assert.commandWorked(res); + assert.eq(4, res.counts.input); + assert.eq(res.result, outColl.getName()); + + assert.eq( + 3, + outColl.find().count(), + () => + `expected 3 distinct tags: ['a', 'b', 'c'], found ${tojson(outColl.find().toArray())}`); + const keys = {}; + for (let result of outColl.find().toArray()) { + keys[result._id] = result.value.count; + } + assert.eq(3, Object.keySet(keys).length, Object.keySet(keys)); + assert.eq(2, keys.a, () => `Expected 2 occurences of the tag 'a': ${tojson(keys)}`); + assert.eq(3, keys.b, () => `Expected 3 occurences of the tag 'b': ${tojson(keys)}`); + assert.eq(3, keys.c, () => `Expected 3 occurences of the tag 'c': ${tojson(keys)}`); + outColl.drop(); +})(); + +(function testMapReduceWithPredicate() { + const res = db.runCommand({ + mapReduce: coll.getName(), + map: mapToObj, + reduce: reduceObjs, + query: {x: {$gt: 2}}, + out: outColl.getName() + }); + assert.commandWorked(res); + assert.eq(2, res.counts.input, () => tojson(res)); + assert.eq(res.result, outColl.getName()); + const keys = {}; + for (let result of outColl.find().toArray()) { + keys[result._id] = result.value.count; + } + assert.eq(3, Object.keySet(keys).length, Object.keySet(keys)); + assert.eq(1, keys.a, () => `Expected 1 occurence of the tag 'a': ${tojson(keys)}`); + assert.eq(1, keys.b, () => `Expected 1 occurence of the tag 'b': ${tojson(keys)}`); + assert.eq(2, keys.c, () => `Expected 2 occurences of the tag 'c': ${tojson(keys)}`); + outColl.drop(); +}()); + +function mapToNumber() { + for (let tag of this.tags) { + emit(tag, 1); + } +} + +function reduceNumbers(key, values) { + let total = 0; + for (let val of values) { + total += val; + } + return total; +} + +// Now do a similar test but using the above map and reduce functions which use numbers as the value +// instead of objects. +(function testBasicMapReduceWithNumberValues() { + const res = db.runCommand({ + mapReduce: coll.getName(), + map: mapToNumber, + reduce: reduceNumbers, + query: {x: {$gt: 2}}, + out: outColl.getName() + }); + assert.commandWorked(res); + assert.eq(2, res.counts.input, () => tojson(res)); + assert.eq(res.result, outColl.getName()); + const keys = {}; + for (let result of outColl.find().toArray()) { + keys[result._id] = result.value; + } + assert.eq(3, Object.keySet(keys).length, Object.keySet(keys)); + assert.eq(1, keys.a, () => `Expected 1 occurence of the tag 'a': ${tojson(keys)}`); + assert.eq(1, keys.b, () => `Expected 1 occurence of the tag 'b': ${tojson(keys)}`); + assert.eq(2, keys.c, () => `Expected 2 occurences of the tag 'c': ${tojson(keys)}`); + outColl.drop(); +}()); + +(function testMapReduceWithManyValuesGrouped() { + const bulk = coll.initializeUnorderedBulkOp(); + for (let i = 5; i < 1000; i++) { + bulk.insert({x: i, tags: ["b", "d"]}); + } + assert.commandWorked(bulk.execute()); + + const res = db.runCommand( + {mapReduce: coll.getName(), map: mapToObj, reduce: reduceObjs, out: outColl.getName()}); + assert.commandWorked(res); + assert.eq(999, res.counts.input, () => tojson(res)); + assert.eq(res.result, outColl.getName()); + assert.eq(4, + outColl.find().count(), + () => `expected 4 distinct tags: ['a', 'b', 'c', 'd'], found ${ + tojson(outColl.find().toArray())}`); + assert.eq("a,b,c,d", outColl.distinct("_id")); + + assert.eq(2, outColl.findOne({_id: "a"}).value.count, () => outColl.findOne({_id: "a"})); + assert.eq(998, outColl.findOne({_id: "b"}).value.count, () => outColl.findOne({_id: "b"})); + assert.eq(3, outColl.findOne({_id: "c"}).value.count, () => outColl.findOne({_id: "c"})); + assert.eq(995, outColl.findOne({_id: "d"}).value.count, () => outColl.findOne({_id: "d"})); + outColl.drop(); +}()); + +(function testThatVerboseOptionIncludesTimingInformation() { + const cmd = + {mapReduce: coll.getName(), map: mapToObj, reduce: reduceObjs, out: outColl.getName()}; + const withoutVerbose = assert.commandWorked(db.runCommand(cmd)); + // TODO SERVER-43290 The verbose option should have the same effect on mongos. + assert(FixtureHelpers.isMongos(db) || !withoutVerbose.hasOwnProperty("timing")); + const withVerbose = assert.commandWorked(db.runCommand(Object.merge(cmd, {verbose: true}))); + assert(withVerbose.hasOwnProperty("timing")); +}()); + +(function testMapReduceAgainstNonExistentCollection() { + assert.commandFailedWithCode(db.runCommand({ + mapReduce: "lasjdlasjdlasjdjasldjalsdj12e", + map: mapToObj, + reduce: reduceObjs, + out: outColl.getName() + }), + ErrorCodes.NamespaceNotFound); +}()); + +(function testHighCardinalityKeySet() { + let correctValues = {}; + + coll.drop(); + const bulk = coll.initializeUnorderedBulkOp(); + for (let i = 0; i < 20000; i++) { + const tag = "Z" + i % 10000; + if (!correctValues[tag]) + correctValues[tag] = 1; + else + correctValues[tag]++; + bulk.insert({x: i, tags: [tag]}); + } + assert.commandWorked(bulk.execute()); + + const res = db.runCommand( + {mapReduce: coll.getName(), out: outColl.getName(), map: mapToObj, reduce: reduceObjs}); + assert.commandWorked(res); + assert.eq(res.result, outColl.getName()); + let actualValues = {}; + outColl.find().forEach(function(resultDoc) { + actualValues[resultDoc._id] = resultDoc.value.count; + }); + for (let key in actualValues) { + assert.eq(correctValues[key], actualValues[key], key); + } +}()); + +coll.drop(); +outColl.drop(); +}()); |