summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jstests/noPassthrough/operator_counters_expressions.js181
1 files changed, 136 insertions, 45 deletions
diff --git a/jstests/noPassthrough/operator_counters_expressions.js b/jstests/noPassthrough/operator_counters_expressions.js
index 1a3fe111d93..8024c545f6b 100644
--- a/jstests/noPassthrough/operator_counters_expressions.js
+++ b/jstests/noPassthrough/operator_counters_expressions.js
@@ -1,6 +1,5 @@
/**
* Tests aggregate expression counters.
- * Initially limited to $getField and $setField.
* @tags: [
* ]
*/
@@ -24,30 +23,65 @@ for (let i = 0; i < 3; i++) {
}));
}
-function checkCounterIncrement(command, exprCounter) {
- const origCounter = db.serverStatus().metrics.operatorCounters.expressions[exprCounter];
+/**
+ * Execute the `command` and compare the operator counters with the expected values.
+ * @param {*} command to be executed.
+ * @param {*} expectedCounters expected operator counters.
+ */
+function checkCounters(command, expectedCounters) {
+ const origCounters = db.serverStatus().metrics.operatorCounters.expressions;
+
command();
- assert.gt(db.serverStatus().metrics.operatorCounters.expressions[exprCounter], origCounter);
+
+ const newCounters = db.serverStatus().metrics.operatorCounters.expressions;
+ let actualCounters = {};
+ for (let ec in origCounters) {
+ const diff = newCounters[ec] - origCounters[ec];
+ if (diff !== 0) {
+ actualCounters[ec] = diff;
+ }
+ }
+
+ assert.docEq(expectedCounters, actualCounters);
+}
+
+/**
+ * Check operator counters in the `find`.
+ * @param {*} query to be executed.
+ * @param {*} expectedCounters - expected operator counters.
+ * @param {*} expectedCount - expected number of records returned by the `find` function.
+ */
+function checkFindCounters(query, expectedCounters, expectedCount) {
+ checkCounters(() => assert.eq(expectedCount, coll.find(query).itcount()), expectedCounters);
+}
+
+/**
+ * Check operator counters in the `aggregate`.
+ * @param {*} pipeline to be executed.
+ * @param {*} expectedCounters - expected operator counters.
+ * @param {*} expectedCount - expected number of records returned by the `find` function.
+ */
+function checkAggregationCounters(pipeline, expectedCounters, expectedCount) {
+ checkCounters(() => assert.eq(expectedCount, coll.aggregate(pipeline).itcount()),
+ expectedCounters);
}
// Find.
-checkCounterIncrement(
- () => assert.eq(3, coll.find({$expr: {$eq: [{$getField: "a$b"}, "foo"]}}).itcount()),
- "$getField");
+checkFindCounters(
+ {$expr: {$eq: [{$getField: "a$b"}, "foo"]}}, {"$getField": 2, "$eq": 2, "$const": 2}, 3);
// Update.
-checkCounterIncrement(
- () => assert.commandWorked(
- coll.update({_id: 0, $expr: {$eq: [{$getField: {field: "a$b", input: "$$ROOT"}}, "foo"]}},
- {$set: {y: 10}})),
- "$getField");
+checkCounters(() => assert.commandWorked(coll.update(
+ {_id: 0, $expr: {$eq: [{$getField: {field: "a$b", input: "$$ROOT"}}, "foo"]}},
+ {$set: {y: 10}})),
+ {"$getField": 4, "$const": 6, "$eq": 4});
-checkCounterIncrement(
+checkCounters(
() => assert.commandWorked(coll.update(
{_id: 1}, [{$replaceWith: {$setField: {field: "a.b", input: "$$ROOT", value: "qqq"}}}])),
- "$setField");
+ {"$setField": 1});
-checkCounterIncrement(() => assert.commandWorked(db.runCommand({
+checkCounters(() => assert.commandWorked(db.runCommand({
update: coll.getName(),
updates: [{
q: {_id: 1},
@@ -55,30 +89,30 @@ checkCounterIncrement(() => assert.commandWorked(db.runCommand({
upsert: false
}]
})),
- "$setField");
+ {"$setField": 1});
// Delete.
-checkCounterIncrement(() => assert.commandWorked(db.runCommand({
+checkCounters(() => assert.commandWorked(db.runCommand({
delete: coll.getName(),
deletes: [{q: {"_id": {$gt: 1}, $expr: {$eq: [{$getField: "a$b"}, "foo"]}}, limit: 1}]
})),
- "$getField");
+ {"$getField": 4, "$eq": 4, "$const": 6});
// In aggregation pipeline.
let pipeline = [{$project: {_id: 1, test: {$getField: "a$b"}}}];
-checkCounterIncrement(() => assert.eq(2, coll.aggregate(pipeline).itcount()), "$getField");
+checkAggregationCounters(pipeline, {"$getField": 5, "$const": 4}, 2);
pipeline = [{$match: {_id: 1, $expr: {$eq: [{$getField: "a$b"}, "foo"]}}}];
-checkCounterIncrement(() => assert.eq(1, coll.aggregate(pipeline).itcount()), "$getField");
+checkAggregationCounters(pipeline, {"$getField": 5, "$eq": 5, "$const": 6}, 1);
pipeline =
[{$match: {_id: 1, $expr: {$eq: [{$getField: {field: "a$b", input: {"a$b": "b"}}}, "b"]}}}];
-checkCounterIncrement(() => assert.eq(1, coll.aggregate(pipeline).itcount()), "$getField");
+checkAggregationCounters(pipeline, {"$getField": 5, "$const": 9, "$eq": 5}, 1);
pipeline = [{
$project: {_id: 1, test: {$setField: {field: {$const: "a.b"}, input: "$$ROOT", value: "barrr"}}}
}];
-checkCounterIncrement(() => assert.eq(2, coll.aggregate(pipeline).itcount()), "$setField");
+checkAggregationCounters(pipeline, {"$setField": 5, "$const": 9}, 2);
// With sub-pipeline.
const testColl = db.operator_counters_expressions2;
@@ -102,7 +136,7 @@ pipeline = [
}
}
];
-checkCounterIncrement(() => assert.eq(3, coll.aggregate(pipeline).itcount()), "$getField");
+checkAggregationCounters(pipeline, {"$getField": 10, "$const": 8}, 3);
initTestColl(5);
pipeline = [
@@ -111,7 +145,7 @@ pipeline = [
pipeline: [{$project: {x: 1, _id: 0, test: {$getField: "a$b"}}}],
as: "joinedField"
}}];
-checkCounterIncrement(() => assert.eq(2, coll.aggregate(pipeline).itcount()), "$getField");
+checkAggregationCounters(pipeline, {"$getField": 9, "$const": 6}, 2);
initTestColl(1);
let mergePipeline =
@@ -120,39 +154,96 @@ pipeline = [{
$merge:
{into: testColl.getName(), on: "_id", whenMatched: mergePipeline, whenNotMatched: "insert"}
}];
-checkCounterIncrement(() => {
+checkCounters(() => {
coll.aggregate(pipeline).itcount();
assert.eq(2, testColl.find().itcount());
-}, "$setField");
+}, {"$setField": 4, "$const": 4});
// Expressions in view pipeline.
db.view.drop();
let viewPipeline = [{$match: {$expr: {$eq: [{$getField: "a.b"}, "bar"]}}}];
assert.commandWorked(
db.runCommand({create: "view", viewOn: coll.getName(), pipeline: viewPipeline}));
-checkCounterIncrement(() => db.view.find().itcount(), "$getField");
+checkCounters(() => db.view.find().itcount(), {"$getField": 3, "$const": 2, "$eq": 3});
// Expressions in document validator.
-const initCounter = db.serverStatus().metrics.operatorCounters.expressions["$getField"];
-initTestColl(1);
-assert.commandWorked(db.runCommand(
- {"collMod": testColl.getName(), "validator": {$expr: {$eq: [{$getField: "a$b"}, "new"]}}}));
-const validatorCounter = db.serverStatus().metrics.operatorCounters.expressions["$getField"];
-assert.gt(validatorCounter, initCounter);
+checkCounters(() => {
+ initTestColl(1);
+ assert.commandWorked(db.runCommand(
+ {"collMod": testColl.getName(), "validator": {$expr: {$eq: [{$getField: "a$b"}, "new"]}}}));
+}, {"$getField": 1, "$eq": 1});
// Expression counter is not incremented for each validated document.
-assert.commandWorked(testColl.insert({
- _id: 2,
- x: 2,
- "a$b": "new",
-}));
-assertDocumentValidationFailure(testColl.insert({
- _id: 3,
- x: 3,
- "a$b": "invalid",
-}),
- testColl);
-assert.eq(validatorCounter, db.serverStatus().metrics.operatorCounters.expressions["$getField"]);
+checkCounters(() => {
+ assert.commandWorked(testColl.insert({
+ _id: 2,
+ x: 2,
+ "a$b": "new",
+ }));
+ assertDocumentValidationFailure(testColl.insert({
+ _id: 3,
+ x: 3,
+ "a$b": "invalid",
+ }),
+ testColl);
+}, {});
+
+// $cond
+pipeline = [{$project: {item: 1, discount: {$cond: {if: {$gte: ["$x", 1]}, then: 10, else: 0}}}}];
+checkAggregationCounters(pipeline, {"$cond": 5, "$gte": 5, "$const": 12}, 2);
+
+// $ifNull
+pipeline = [{$project: {description: {$ifNull: ["$description", "Unspecified"]}}}];
+checkAggregationCounters(pipeline, {"$ifNull": 5, "$const": 4}, 2);
+
+// $divide, $switch
+let query = {
+ $expr: {
+ $eq: [
+ {
+ $switch: {
+ branches: [{case: {$gt: ["$x", 0]}, then: {$divide: ["$x", 2]}}],
+ default: {$subtract: [100, "$x"]}
+ }
+ },
+ 100
+ ]
+ }
+};
+checkFindCounters(
+ query, {"$const": 4, "$divide": 2, "$subtract": 2, "$eq": 2, "$gt": 2, "$switch": 2}, 1);
+
+// $cmp, $exp, $abs, $range
+pipeline = [{
+ $project: {
+ cmpField: {$cmp: ["$x", 250]},
+ expField: {$exp: "$x"},
+ absField: {$abs: "$x"},
+ rangeField: {$range: [0, "$x", 25]}
+ }
+}];
+checkAggregationCounters(pipeline, {"$abs": 5, "$cmp": 5, "$const": 12, "$exp": 5, "$range": 5}, 2);
+
+// $or
+pipeline = [{$match: {$expr: {$or: [{$eq: ["$_id", 0]}, {$eq: ["$x", 1]}]}}}];
+checkAggregationCounters(pipeline, {"$const": 2, "$eq": 6, "$or": 3}, 2);
+
+// $dateFromParts
+pipeline =
+ [{$project: {date: {$dateFromParts: {'year': 2021, 'month': 10, 'day': {$add: ['$x', 10]}}}}}];
+checkAggregationCounters(pipeline, {"$add": 5, "$const": 12, "$dateFromParts": 5}, 2);
+
+// $concat
+pipeline = [{$project: {mystring: {$concat: [{$getField: "a$b"}, {$getField: "a.b"}]}}}];
+checkAggregationCounters(pipeline, {"$concat": 5, "$const": 8, "$getField": 10}, 2);
+
+// $toDouble
+pipeline = [{$project: {doubleval: {$toDouble: "$_id"}}}];
+checkAggregationCounters(pipeline, {"$const": 4, "$convert": 4, "$toDouble": 1}, 2);
+
+// $setIntersection
+pipeline = [{$project: {intersection: {$setIntersection: [[1, 2, 3], [3, 2]]}}}];
+checkAggregationCounters(pipeline, {"$const": 8, "$setIntersection": 2}, 2);
MongoRunner.stopMongod(mongod);
})();