summaryrefslogtreecommitdiff
path: root/jstests/aggregation/expressions/internal_js_emit.js
blob: 7f8f1f4f38c2dc0647569e4bd734bd67b235d51a (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
// Tests basic functionality of the $_internalJsEmit expression, which provides capability for the
// map stage of MapReduce.
(function() {
"use strict";

load('jstests/aggregation/extras/utils.js');

const coll = db.js_emit_expr;
coll.drop();

function fmap() {
    for (let word of this.text.split(' ')) {
        emit(word, 1);
    }
}

let pipeline = [
    {
        $project: {
            emits: {
                $_internalJsEmit: {
                    'this': '$$ROOT',
                    'eval': fmap,
                },
            },
            _id: 0,
        }
    },
    {$unwind: '$emits'},
    {$replaceRoot: {newRoot: '$emits'}}
];

assert.commandWorked(coll.insert({text: 'hello world'}));

let results = coll.aggregate(pipeline, {cursor: {batchSize: 1}}).toArray();
assert(resultsEq(results, [{k: "hello", v: 1}, {k: "world", v: 1}]), results);

assert.commandWorked(coll.insert({text: 'mongo db'}));

// Set batchSize to 1 to check that the expression is able to run across getMore's.
results = coll.aggregate(pipeline, {cursor: {batchSize: 1}}).toArray();
assert(resultsEq(results,
                 [{k: 'hello', v: 1}, {k: 'world', v: 1}, {k: 'mongo', v: 1}, {k: 'db', v: 1}]),
       results);

// Test that the 'eval' function accepts a string argument.
pipeline[0].$project.emits.$_internalJsEmit.eval = fmap.toString();
results = coll.aggregate(pipeline, {cursor: {batchSize: 1}}).toArray();
assert(resultsEq(results,
                 [{k: 'hello', v: 1}, {k: 'world', v: 1}, {k: 'mongo', v: 1}, {k: 'db', v: 1}]),
       results);

// Test that the command correctly fails for an invalid operation within the JS function.
assert.commandWorked(coll.insert({text: 5}));
assert.commandFailedWithCode(
    db.runCommand({aggregate: coll.getName(), pipeline: pipeline, cursor: {}}),
    ErrorCodes.JSInterpreterFailure);

// Test that the command correctly fails for invalid arguments.
pipeline = [{
    $project: {
        emits: {
            $_internalJsEmit: {
                'this': 'must evaluate to an object',
                'eval': fmap,
            },
        },
        _id: 0,
    }
}];
assert.commandFailedWithCode(
    db.runCommand({aggregate: coll.getName(), pipeline: pipeline, cursor: {}}), 31225);

pipeline = [{
    $project: {
        emits: {
            $_internalJsEmit: {
                'this': '$$ROOT',
                'eval': 'this is not a valid function!',
            },
        },
        _id: 0,
    }
}];
assert.commandFailedWithCode(
    db.runCommand({aggregate: coll.getName(), pipeline: pipeline, cursor: {}}),
    ErrorCodes.JSInterpreterFailure);
})();