Files
mongo/jstests/sharding/query/map_reduce_invalid_output_collection.js

130 lines
5.2 KiB
JavaScript

// Test that mapReduce correctly fails if the target collection is not unsharded or sharded by just
// _id.
(function() {
"use strict";
const st = new ShardingTest({shards: 2, mongos: 2});
const dbName = jsTest.name();
const nsString = dbName + ".coll";
const numDocs = 50000;
const numKeys = 1000;
assert.commandWorked(st.s.adminCommand({enableSharding: dbName}));
st.ensurePrimaryShard(dbName, st.shard0.shardName);
assert.commandWorked(st.s.adminCommand({shardCollection: nsString, key: {key: 1}}));
// Load chunk data through the stale mongos before moving a chunk.
const staleMongos1 = st.s1;
staleMongos1.getCollection(nsString).find().itcount();
assert.commandWorked(st.s.adminCommand({split: nsString, middle: {key: numKeys / 2}}));
assert.commandWorked(
st.s.adminCommand({moveChunk: nsString, find: {key: 0}, to: st.shard1.shardName}));
const bulk = st.s.getCollection(nsString).initializeUnorderedBulkOp();
for (let i = 0; i < numDocs; i++) {
bulk.insert({_id: i, key: (i % numKeys), value: i % numKeys});
}
assert.commandWorked(bulk.execute());
const map = function() {
emit(this.key, this.value);
};
const reduce = function(k, values) {
let total = 0;
for (let i = 0; i < values.length; i++) {
total += values[i];
}
return total;
};
// Create and shard the output collection, with a shard key other than _id.
const outColl = "mr_out";
assert.commandWorked(
st.s.adminCommand({shardCollection: dbName + "." + outColl, key: {not_id: 1}}));
// Insert a document into the output collection such that it is not dropped and recreated by the
// legacy mapReduce.
assert.commandWorked(st.s.getDB(dbName).getCollection(outColl).insert({_id: -1, not_id: 0}));
// Through the same mongos, verify that mapReduce fails since the output collection is not sharded
// by _id.
assert.commandFailedWithCode(
st.s.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {merge: outColl, sharded: true}}),
31313);
assert.commandFailedWithCode(
st.s.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {reduce: outColl, sharded: true}}),
31313);
// Expect a similar failure through a stale mongos.
assert.commandFailedWithCode(
staleMongos1.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {merge: outColl, sharded: true}}),
31313);
// Mode replace is unique, since the legacy mapReduce will unconditionally drop and reshard the
// target collection on _id.
assert.commandFailedWithCode(
st.s.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {replace: outColl, sharded: true}}),
31313);
function testAgainstValidShardedOutput(shardKey) {
// Drop and reshard the target collection.
st.s.getDB(dbName).getCollection(outColl).drop();
assert.commandWorked(
st.s.adminCommand({shardCollection: dbName + "." + outColl, key: shardKey}));
// Insert a document into the output collection such that it is not dropped and recreated by the
// legacy mapReduce.
assert.commandWorked(st.s.getDB(dbName).getCollection(outColl).insert({_id: -1}));
// Test that mapReduce succeeds since the target collection is sharded by _id.
assert.commandWorked(st.s.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {merge: outColl, sharded: true}}));
// Run the same mapReduce through a stale mongos and expect it to pass as well.
assert.commandWorked(st.s.getDB(dbName).getCollection(outColl).remove({}));
assert.commandWorked(staleMongos1.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {merge: outColl, sharded: true}}));
}
// Test against output collection sharded by {_id: 1}.
testAgainstValidShardedOutput({_id: 1});
// Test against output collection sharded by {_id: "hashed"}.
testAgainstValidShardedOutput({_id: "hashed"});
// Test that MR fails if the output collection is sharded by a compound key including _id.
(function testCompoundShardKey() {
// Drop and reshard the target collection.
st.s.getDB(dbName).getCollection(outColl).drop();
assert.commandWorked(
st.s.adminCommand({shardCollection: dbName + "." + outColl, key: {_id: 1, a: 1}}));
// Insert a document into the output collection such that it is not dropped and recreated by the
// legacy mapReduce.
assert.commandWorked(st.s.getDB(dbName).getCollection(outColl).insert({_id: -1, a: 1}));
// Test that mapReduce succeeds since the target collection is not sharded by only _id.
assert.commandFailedWithCode(
st.s.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {merge: outColl, sharded: true}}),
31313);
// Run the same mapReduce through a stale mongos and expect it to fail as well. Make sure to
// leave at least one document in the target collection for the same reason as above.
assert.commandWorked(st.s.getDB(dbName).getCollection(outColl).remove({_id: {$gt: 0}}));
assert.commandFailedWithCode(
staleMongos1.getDB(dbName).runCommand(
{mapReduce: "coll", map: map, reduce: reduce, out: {merge: outColl, sharded: true}}),
31313);
})();
st.stop();
})();