summaryrefslogtreecommitdiff
path: root/jstests/noPassthroughWithMongod/group_pushdown.js
diff options
context:
space:
mode:
Diffstat (limited to 'jstests/noPassthroughWithMongod/group_pushdown.js')
-rw-r--r--jstests/noPassthroughWithMongod/group_pushdown.js212
1 files changed, 212 insertions, 0 deletions
diff --git a/jstests/noPassthroughWithMongod/group_pushdown.js b/jstests/noPassthroughWithMongod/group_pushdown.js
index ba7b51a7b44..3125d68d414 100644
--- a/jstests/noPassthroughWithMongod/group_pushdown.js
+++ b/jstests/noPassthroughWithMongod/group_pushdown.js
@@ -229,6 +229,194 @@ assertResultsMatchWithAndWithoutPushdown(
assertResultsMatchWithAndWithoutPushdown(
coll, pipeline, [{_id: "a", ss: 30}, {_id: "b", ss: 60}, {_id: "c", ss: 10}], 2));
+// The second $group stage refers to a top-field below a $switch
+assertResultsMatchWithAndWithoutPushdown(coll,
+ [
+ {$group: {_id: {$divide: ["$price", 5]}}},
+ {
+ $group: {
+ _id: null,
+ lowp: {
+ $sum: {
+ $switch: {
+ branches: [{
+ case: {$lte: ["$_id", 3]},
+ then: 1
+ }],
+ default: 0
+ }
+ }
+ },
+ highp: {
+ $sum: {
+ $switch: {
+ branches: [{
+ case: {$gt: ["$_id", 3]},
+ then: 1
+ }],
+ default: 0
+ }
+ }
+ }
+ }
+ }
+ ],
+ [{"_id": null, "lowp": 2, "highp": 1}],
+ 2);
+
+// The second $group stage refers to a top-field below a $cond
+assertResultsMatchWithAndWithoutPushdown(
+ coll,
+ [
+ {$group: {_id: {$divide: ["$price", 5]}}},
+ {
+ $group: {
+ _id: null,
+ lowp: {$sum: {$cond: [{$lte: ["$_id", 3]}, 1, 0]}},
+ highp: {$sum: {$cond: [{$gt: ["$_id", 3]}, 1, 0]}}
+ }
+ }
+ ],
+ [{"_id": null, "lowp": 2, "highp": 1}],
+ 2);
+
+// The second $group stage refers to a top-field below a nested $cond / $ifNull
+assertResultsMatchWithAndWithoutPushdown(coll,
+ [
+ {$group: {_id: {$divide: ["$price", 5]}}},
+ {
+ $group: {
+ _id: null,
+ lowp: {
+ $sum: {
+ $cond: [
+ {
+ $lte:
+ [{$ifNull: ["$_id", 0]}, 3]
+ },
+ 1,
+ 0
+ ]
+ }
+ },
+ highp: {
+ $sum: {
+ $cond: [
+ {$gt: [{$ifNull: ["$_id", 0]}, 3]},
+ 1,
+ 0
+ ]
+ }
+ }
+ }
+ }
+ ],
+ [{"_id": null, "lowp": 2, "highp": 1}],
+ 2);
+
+// The second $group stage refers to top-fields below a $filter
+assertResultsMatchWithAndWithoutPushdown(
+ coll,
+ [
+ {$group: {_id: "$item", prices: {$push: "$price"}}},
+ {
+ $group: {
+ _id: "$_id",
+ o: {$push: {$filter: {input: "$prices", as: "p", cond: {$gte: ["$$p", 5]}}}}
+ }
+ }
+ ],
+ [{"_id": "a", "o": [[10, 5]]}, {"_id": "b", "o": [[20, 10]]}, {"_id": "c", "o": [[5]]}],
+ 2);
+
+// The second $group stage refers to top-fields below a $let
+assertResultsMatchWithAndWithoutPushdown(
+ coll,
+ [
+ {$group: {
+ _id: "$item", maxp: {$max: "$price"}, minp: {$min: "$price"}, count: {$count: {}}
+ }},
+ {$group: {_id: "$_id", o: {$sum: {
+ $let: {
+ vars: {
+ minPlusMax: {$add: ["$maxp", "$minp"]},
+ count: "$count"
+ },
+ in: {$multiply: ["$$minPlusMax", "$$count"]}
+ }
+ }}}}
+ ],
+ [{ "_id" : "a", "o" : 30 }, { "_id" : "c", "o" : 10 }, { "_id" : "b", "o" : 60 }],
+ 2);
+
+// The second $group stage refers to top-fields below a $and
+assertResultsMatchWithAndWithoutPushdown(coll,
+ [
+ {
+ $group: {
+ _id: "$item",
+ maxp: {$max: "$price"},
+ minp: {$min: "$price"}
+ }
+ },
+ {
+ $group:
+ {
+ _id: "$_id",
+ o:
+ {
+ $sum:
+ {
+ $and: [
+ {$gt: ["$maxp", 15]},
+ {$lt: ["$minp", 10]}
+ ]
+ }
+ }
+ }
+ }
+ ],
+ [
+ {"_id": "a", "o": 0},
+ {"_id": "c", "o": 0},
+ {"_id": "b", "o": 0}
+ ],
+ 2);
+
+// The second $group stage refers to top-fields below a $or
+assertResultsMatchWithAndWithoutPushdown(coll,
+ [
+ {
+ $group: {
+ _id: "$item",
+ maxp: {$max: "$price"},
+ minp: {$min: "$price"}
+ }
+ },
+ {
+ $group:
+ {
+ _id: "$_id",
+ o:
+ {
+ $sum:
+ {
+ $or: [
+ {$gt: ["$maxp", 15]},
+ {$lt: ["$minp", 10]}
+ ]
+ }
+ }
+ }
+ }
+ ],
+ [
+ {"_id": "a", "o": 0},
+ {"_id": "c", "o": 0},
+ {"_id": "b", "o": 0}
+ ],
+ 2);
+
// The second $group stage refers to both a top-level field and a sub-field twice which does not
// exist.
assertResultsMatchWithAndWithoutPushdown(
@@ -262,6 +450,17 @@ assertResultsMatchWithAndWithoutPushdown(
[{"_id": 1, o: 1}],
1);
+// The second $group does not have top-level fields.
+assertResultsMatchWithAndWithoutPushdown(
+ coll,
+ [
+ {$group: {_id: {a: "$item", b: "$quantity"}, price: {$avg: "$price"}}},
+ {$group: {_id: {a: "$_id.a", b: "$_id.b"}, price: {$sum: "$price"}}},
+ {$group: {_id: '', price: {$avg: "$price"}}}
+ ],
+ [{"_id": "", "price": 10}],
+ 3);
+
// Run a group with a supported $stdDevSamp accumultor and check that it gets pushed down.
assertGroupPushdown(coll,
[{$group: {_id: "$item", s: {$stdDevSamp: "$quantity"}}}],
@@ -533,4 +732,17 @@ assertNoGroupPushdown(coll, basicGroup, basicGroupResults);
// Reset 'internalQuerySlotBasedExecutionDisableGroupPushdown' to its original value.
assert.commandWorked(db.adminCommand(
{setParameter: 1, internalQuerySlotBasedExecutionDisableGroupPushdown: oldValue}));
+
+(function testConstNothingForIdMappedToNull() {
+ // Prepare a collection.
+ const coll = db.nothing_id;
+ coll.drop();
+ coll.insert({_id: 0});
+
+ // $$REMOVE produce Nothing constant and it should be converted to Null. Without an accumulator
+ // $group is not pushed down and we need an accumulator.
+ assert.eq(
+ coll.aggregate([{$group: {_id: "$$REMOVE", o: {$first: "$non_existent_field"}}}]).toArray(),
+ [{_id: null, o: null}]);
+})();
})();