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
|
/**
* Tests for the $percentile expression syntax.
* @tags: [
* requires_fcv_70,
* featureFlagApproxPercentiles
* ]
*/
(function() {
"use strict";
load("jstests/aggregation/extras/utils.js");
const coll = db.expression_percentile;
coll.drop();
assert.commandWorked(coll.insert([{_id: 0, k1: 3, k2: 2, k3: "hi", k4: [1, 2, 3]}]));
/**
* Tests to check that invalid $percentile specifications are rejected.
*/
function assertInvalidSyntax(percentileSpec, msg) {
assert.commandFailed(
coll.runCommand("aggregate", {pipeline: [{$project: {p: percentileSpec}}], cursor: {}}),
msg);
}
assertInvalidSyntax({$percentile: 0.5}, "Should fail if $percentile is not an object");
assertInvalidSyntax({$percentile: {input: ["$k1", "$k2"], method: "approximate"}},
"Should fail if $percentile is missing 'p' field");
assertInvalidSyntax({$percentile: {p: [0.5], method: "approximate"}},
"Should fail if $percentile is missing 'input' field");
assertInvalidSyntax({$percentile: {p: [0.5], input: "$k1"}},
"Should fail if $percentile is missing 'method' field");
assertInvalidSyntax(
{$percentile: {p: [0.5], input: ["$k1", "$k2"], method: "approximate", extras: 42}},
"Should fail if $percentile contains an unexpected field");
assertInvalidSyntax({$percentile: {p: 0.5, input: ["$k1", "$k2"], method: "approximate"}},
"Should fail if 'p' field in $percentile isn't array");
assertInvalidSyntax({$percentile: {p: [], input: ["$k1", "$k2"], method: "approximate"}},
"Should fail if 'p' field in $percentile is an empty array");
assertInvalidSyntax({$percentile: {p: [0.5], input: [], method: "approximate"}},
"Should fail if 'input' field in $percentile is an empty array");
assertInvalidSyntax(
{$percentile: {p: [0.5, "foo"], input: ["$k1", "$k2"], method: "approximate"}},
"Should fail if 'p' field in $percentile is an array with a non-numeric element");
assertInvalidSyntax(
{$percentile: {p: [0.5, 10], input: ["$k1", "$k2"], method: "approximate"}},
"Should fail if 'p' field in $percentile is an array with any value outside of [0, 1] range");
assertInvalidSyntax({$percentile: {p: [0.5, 0.7], input: ["$k1", "$k2"], method: 42}},
"Should fail if 'method' field isn't a string");
assertInvalidSyntax({$percentile: {p: [0.5, 0.7], input: ["$k1", "$k2"], method: "fancy"}},
"Should fail if 'method' isn't one of _predefined_ strings");
/**
* Tests for $median. $median desugars to $percentile with the field p:[0.5] added, and therefore
* has similar syntax to $percentile.
*/
assertInvalidSyntax({$median: {p: [0.5], input: "$k4", method: "approximate"}},
"Should fail if 'p' is defined");
assertInvalidSyntax({$median: {method: "approximate"}},
"Should fail if $median is missing 'input' field");
assertInvalidSyntax({$median: {input: [], method: "approximate"}},
"Should fail if $median has an empty array as its 'input' field");
assertInvalidSyntax({$median: {input: ["$k1", "$k2"]}},
"Should fail if $median is missing 'method' field");
assertInvalidSyntax({$median: {input: "$x", method: "approximate", extras: 42}},
"Should fail if $median contains an unexpected field");
/**
* Test that valid $percentile specifications are accepted. The results, i.e. semantics, are
* tested elsewhere and would cover all of the cases below, we are providing them here
* nonetheless for completeness.
*/
function assertValidSyntax(percentileSpec, msg) {
assert.commandWorked(
coll.runCommand("aggregate", {pipeline: [{$project: {p: percentileSpec}}], cursor: {}}),
msg);
}
assertValidSyntax(
{$percentile: {p: [0.0, 0.0001, 0.5, 0.995, 1.0], input: ["$k1"], method: "approximate"}},
"Should be able to specify an array of percentiles");
assertValidSyntax({$percentile: {p: [0.5, 0.9], input: ["k3"], method: "approximate"}},
"Non-numeric expressions in input array should be gracefully ignored");
assertValidSyntax({$percentile: {p: [0.5], input: "$k4", method: "approximate"}},
"Should work if 'input' field in $percentile is a single expression");
/**
* Tests for $median. $median desugars to $percentile with the field p:[0.5] added.
*/
assertValidSyntax({$median: {input: "$k4", method: "approximate"}},
"Simple base case for $median with single expression input field");
assertValidSyntax({$median: {input: ["$k1", "$k2"], method: "approximate"}},
"Simple base case for $median with array input field");
})();
|