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
|
/**
* Verifies that time-series collections work as expected with $merge.
*
*
* @tags: [
* does_not_support_stepdowns,
* does_not_support_transactions,
* requires_timeseries,
* ]
*/
(function() {
"use strict";
load("jstests/core/timeseries/libs/timeseries_agg_helpers.js");
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({"tags.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: "tags.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, "tags.hostid": 1, time: 1}},
{$sort: {time: 1}},
{
$merge: {
into: "observer_out",
on: "tags.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();
})();
|