summaryrefslogtreecommitdiff
path: root/jstests/core/timeseries/timeseries_merge.js
blob: 388fba21563b1ff8368ad7f213e98212516a32f1 (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
/**
 * Verifies that time-series collections work as expected with $merge.
 *
 *
 * @tags: [
 *     assumes_unsharded_collection,
 *     does_not_support_transactions,
 *     requires_timeseries,
 *     requires_fcv_49,
 * ]
 */
(function() {
"use strict";

load("jstests/core/timeseries/libs/timeseries_agg_helpers.js");

if (!TimeseriesTest.timeseriesCollectionsEnabled(db.getMongo())) {
    jsTestLog("Skipping test because the time-series collection feature flag is disabled");
    return;
}

const testDB = TimeseriesAggTests.getTestDb();
assert.commandWorked(testDB.dropDatabase());
const numHosts = 10;
const numIterations = 20;

let [inColl, observerInColl] = TimeseriesAggTests.prepareInputCollections(numHosts, numIterations);

// $merge on field requires the output collection to have an unique index on key(s) for "on" field.
function prepareOutputCollectionForMergeOn(outColl) {
    outColl.drop();
    assert.commandWorked(testDB.createCollection(outColl.getName()));

    assert.commandWorked(outColl.createIndex({"hostid": 1}, {unique: true}));
}

/**
 * Verifies that simple $merge works as expected with time-series source collection.
 */
let runSimpleMergeTestCase = () => {
    // Gets the expected results from non time-series observer input collection.
    let expectedResults = TimeseriesAggTests.getOutputAggregateResults(
        observerInColl, [{$merge: {into: "observer_out"}}]);

    // Gets the actual results from time-series input collection.
    let actualResults =
        TimeseriesAggTests.getOutputAggregateResults(inColl, [{$merge: {into: "out"}}]);

    // Verifies that the number of measurements is same as expected.
    assert.eq(actualResults.length, expectedResults.length, actualResults);

    // Verifies that every measurement is same as expected.
    for (var i = 0; i < expectedResults.length; ++i) {
        assert.eq(actualResults[i], expectedResults[i], actualResults);
    }
};

let runMergeOnErrorTestCase = () => {
    var outColl = TimeseriesAggTests.getOutputCollection("out");
    prepareOutputCollectionForMergeOn(outColl);

    // This must fail because source '_id' field will try to replace target '_id' field which is
    // immutable. This verifies that source '_id' is materialized.
    jsTestLog("'ImmutableField' error expected below!");
    var err = assert.throws(() => inColl.aggregate([{
        $merge: {
            into: outColl.getName(),
            on: "hostid",
            whenMatched: "replace",
        }
    }]));
    assert.commandFailedWithCode(err, ErrorCodes.ImmutableField);
};

/**
 * Verifies that $merge "on" field works as expected with time-series source collection.
 */
let runMergeOnTestCase = () => {
    var mergePipeline = [
        {$project: {_id: 0, cpu: 1, idle: 1, hostid: 1, time: 1}},
        {$sort: {time: 1}},
        {
            $merge: {
                into: "observer_out",
                on: "hostid",
                whenMatched: "merge",
            }
        }
    ];

    // Gets the expected results from non time-series observer input collection.
    let expectedResults = TimeseriesAggTests.getOutputAggregateResults(
        observerInColl,
        mergePipeline,
        /*prepareAction*/ (outColl) => prepareOutputCollectionForMergeOn(outColl));

    // Gets the actual results from time-series input collection.
    mergePipeline[mergePipeline.length - 1]["$merge"].into = "out";
    let actualResults = TimeseriesAggTests.getOutputAggregateResults(
        inColl,
        mergePipeline,
        /*prepareAction*/ (outColl) => prepareOutputCollectionForMergeOn(outColl));

    // Verifies that the number of measurements is same as expected.
    assert.eq(actualResults.length, expectedResults.length, actualResults);

    // Verifies that every measurement is same as expected.
    for (var i = 0; i < expectedResults.length; ++i) {
        assert.eq(actualResults[i], expectedResults[i], actualResults);
    }
};

runSimpleMergeTestCase();
runMergeOnErrorTestCase();
runMergeOnTestCase();
})();