summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRui Liu <lriuui0x0@gmail.com>2023-07-14 15:09:02 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2023-08-21 16:18:58 +0000
commit00bd991c1fb5789bab9d93f43efe82ae509085ab (patch)
treeb103efab8bc468d665ca77ab82c033d7c1951b02
parentce4ec8ed4a2afc48dd2ae50b6c95b786d8dfe494 (diff)
SERVER-77183 Only eliminate projection before group when group doesn't require full document
(cherry picked from commit 107f24c1bf0c8f7041978b2dfb718bb6694e0ba5)
-rw-r--r--jstests/aggregation/optimize_away_pipeline.js3
-rw-r--r--src/mongo/db/query/planner_analysis.cpp2
2 files changed, 5 insertions, 0 deletions
diff --git a/jstests/aggregation/optimize_away_pipeline.js b/jstests/aggregation/optimize_away_pipeline.js
index 8dfe8340182..1229b9e7070 100644
--- a/jstests/aggregation/optimize_away_pipeline.js
+++ b/jstests/aggregation/optimize_away_pipeline.js
@@ -647,6 +647,9 @@ assertProjectionIsNotRemoved([{$project: {a: 1}}, {$group: {_id: "$a", s: {$sum:
assertProjectionIsNotRemoved(
[{$project: {a: 1, b: 1}}, {$group: {_id: "$a.b", s: {$sum: "$b.c"}}}]);
+// Test that an inclusion projection is NOT optimized away if group depends on the entire document.
+assertProjectionIsNotRemoved([{$project: {a: 1}}, {$group: {_id: "$$ROOT"}}]);
+
// If the $group depends on both "path" and "path.subpath" then it will generate a $project on only
// "path" to express its dependency set. We then fail to optimize that out. As a future improvement,
// we could improve the optimizer to ensure that a projection stage is not present in the resulting
diff --git a/src/mongo/db/query/planner_analysis.cpp b/src/mongo/db/query/planner_analysis.cpp
index 4e714e1a8a5..6f699824e1a 100644
--- a/src/mongo/db/query/planner_analysis.cpp
+++ b/src/mongo/db/query/planner_analysis.cpp
@@ -716,6 +716,8 @@ void removeInclusionProjectionBelowGroupRecursive(QuerySolutionNode* solnRoot) {
if (auto projection = attemptToGetProjectionFromQuerySolution(*projectNodeCandidate);
// only eliminate inclusion projections
projection && projection.value()->isInclusionOnly() &&
+ // only eliminate when group depends on a subset of fields
+ !groupNode->needWholeDocument &&
// only eliminate projections which preserve all fields used by the group
isSubset(groupNode->requiredFields, projection.value()->getRequiredFields())) {
// Attach the projectNode's child directly as the groupNode's child, eliminating the