summaryrefslogtreecommitdiff
path: root/jstests/core/map_reduce_validation.js
blob: 953bc360626788946a1f95727fc78cf844322706 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Tests that invalid options to the mapReduce command are rejected.
// @tags: [
//   assumes_no_implicit_collection_creation_after_drop,
//   does_not_support_stepdowns,
//   uses_map_reduce_with_temp_collections,
// ]
(function() {
"use strict";

load("jstests/libs/collection_drop_recreate.js");  // For assertDropCollection
load('jstests/libs/fixture_helpers.js');           // For 'FixtureHelpers'

const source = db.mr_validation;
source.drop();
assert.commandWorked(source.insert({x: 1}));

function mapFunc() {
    emit(this.x, 1);
}
function reduceFunc(key, values) {
    return Array.sum(values);
}

// Test that you can't specify sharded and inline.
assert.commandFailed(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {inline: 1, sharded: true}
}));

// Test that you can't output to the admin or config databases.
assert.commandFailedWithCode(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {merge: "foo", db: "admin"}
}),
                             ErrorCodes.CommandNotSupported);

assert.commandFailedWithCode(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {merge: "foo", db: "config"}
}),
                             ErrorCodes.CommandNotSupported);

// Test that you can output to a different database.
// Create the other database.
db.getSiblingDB("mr_validation_other").foo.drop();
assert.commandWorked(db.getSiblingDB("mr_validation_other").createCollection("foo"));
assert.commandWorked(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {merge: "foo", db: "mr_validation_other"}
}));
assert.eq(db.getSiblingDB("mr_validation_other").foo.find().toArray(), [{_id: 1, value: 1}]);

db.mr_nonexistent.drop();
db.out_nonexistent.drop();
const resultWithNonExistent = db.runCommand(
    {mapReduce: "mr_nonexistent", map: mapFunc, reduce: reduceFunc, out: "out_nonexistent"});
if (resultWithNonExistent.ok) {
    // In the implementation which redirects to an aggregation this is expected to succeed and
    // produce an empty output collection.
    assert.commandWorked(resultWithNonExistent);
    assert.eq(db.out_nonexistent.find().itcount(), 0);
} else {
    // In the old MR implementation this is expected to fail.
    assert.commandFailedWithCode(resultWithNonExistent, ErrorCodes.NamespaceNotFound);
}

// Test that you can't use a regex as the namespace.
assert.commandFailed(db.runCommand(
    {mapReduce: /bar/, map: mapFunc, reduce: reduceFunc, out: {replace: "foo", db: "test"}}));

assert.commandFailed(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {replace: /foo/, db: "test"}
}));

assert.commandFailed(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {merge: /foo/, db: "test"}
}));

assert.commandFailed(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {replace: "foo", db: /test/}
}));

assert.commandFailed(db.runCommand({
    mapReduce: source.getName(),
    map: mapFunc,
    reduce: reduceFunc,
    out: {merge: "foo", db: /test/}
}));

// Test that mapReduce fails when run against a view.
assertDropCollection(db, "sourceView");
assert.commandWorked(db.createView("sourceView", source.getName(), [{$project: {_id: 0}}]));
assert.commandFailedWithCode(
    db.runCommand({mapReduce: "sourceView", map: mapFunc, reduce: reduceFunc, out: "foo"}),
    ErrorCodes.CommandNotSupportedOnView);

// The new implementation is not supported in a sharded cluster yet, so avoid running it in the
// passthrough suites.
if (!FixtureHelpers.isMongos(db)) {
    // Test that mapReduce fails when run against a view.
    db.sourceView.drop();
    assert.commandWorked(db.createView("sourceView", source.getName(), [{$project: {_id: 0}}]));
    assert.commandFailedWithCode(
        db.runCommand({mapReduce: "sourceView", map: mapFunc, reduce: reduceFunc, out: "foo"}),
        ErrorCodes.CommandNotSupportedOnView);

    assert.commandFailedWithCode(
        db.runCommand({mapReduce: "sourceView", map: mapFunc, reduce: reduceFunc, out: "foo"}),
        ErrorCodes.CommandNotSupportedOnView);
}

// Test that mapReduce fails gracefully if the query parameter is the wrong type.
assert.throws(() => coll.mapReduce(mapFunc, reduceFunc, {out: outputColl.getName(), query: "foo"}));
}());