diff options
author | Nicholas Zolnierz <nicholas.zolnierz@mongodb.com> | 2022-09-15 15:11:22 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-10-06 20:30:58 +0000 |
commit | c470abdc3d07d42bd6f78a616559b6f311719c80 (patch) | |
tree | 227e5148e2ad559d00b87f76f0185e6bc4fc2836 | |
parent | 8f45eeaecaa95d38263e8bcc9da6ceeb7aa3d1d2 (diff) | |
download | mongo-c470abdc3d07d42bd6f78a616559b6f311719c80.tar.gz |
SERVER-69380 Avoid swapping meta projection with $_internalUnpackBucket if a projection has already been absorbed
(cherry picked from commit d1a117a1abc9ead34fc6399697055a46ca0c1df4)
3 files changed, 55 insertions, 1 deletions
diff --git a/jstests/core/timeseries/timeseries_project.js b/jstests/core/timeseries/timeseries_project.js index 4958ded193a..275a213d354 100644 --- a/jstests/core/timeseries/timeseries_project.js +++ b/jstests/core/timeseries/timeseries_project.js @@ -118,5 +118,10 @@ pipeline = [{$addFields: {a: "$x", b: "$a"}}, {$project: {_id: 0}}]; tsDoc = tsColl.aggregate(pipeline).toArray(); regDoc = regColl.aggregate(pipeline).toArray(); assert.docEq(tsDoc, regDoc); + +pipeline = [{$project: {a: 1, _id: 0}}, {$project: {newMeta: "$x"}}]; +tsDoc = tsColl.aggregate(pipeline).toArray(); +regDoc = regColl.aggregate(pipeline).toArray(); +assert.docEq(tsDoc, regDoc); })(); })(); diff --git a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp index 72251d7a842..a7dc3e7573d 100644 --- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp +++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp @@ -465,7 +465,7 @@ bool DocumentSourceInternalUnpackBucket::pushDownComputedMetaProjection( if (std::next(itr) == container->end()) { return nextStageWasRemoved; } - if (!_bucketUnpacker.bucketSpec().metaField) { + if (!_bucketUnpacker.bucketSpec().metaField || !_bucketUnpacker.includeMetaField()) { return nextStageWasRemoved; } diff --git a/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/optimize_pipeline_test.cpp b/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/optimize_pipeline_test.cpp index 1f190355cd5..ef61bbaf09b 100644 --- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/optimize_pipeline_test.cpp +++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/optimize_pipeline_test.cpp @@ -724,6 +724,55 @@ TEST_F(OptimizePipeline, InternalizeProjectAndPushdownAddFields) { serialized[1]); } +TEST_F(OptimizePipeline, DoNotSwapAddFieldsIfDependencyIsExcluded) { + { + auto unpackSpecObj = fromjson( + "{$_internalUnpackBucket: { exclude: [], timeField: 'time', metaField: 'myMeta', " + "bucketMaxSpanSeconds: 3600}}"); + auto projectSpecObj = fromjson("{$project: {x: true, _id: false}}"); + auto addFieldsSpec = fromjson("{$addFields: {newMeta: '$myMeta'}}"); + + auto pipeline = + Pipeline::parse(makeVector(unpackSpecObj, projectSpecObj, addFieldsSpec), getExpCtx()); + + pipeline->optimizePipeline(); + + // We should internalize the $project but _not_ push down the $addFields because it's field + // dependency has been excluded. Theoretically we could remove the $addFields for this + // trivial except but not always. + auto serialized = pipeline->serializeToBson(); + ASSERT_EQ(2u, serialized.size()); + ASSERT_BSONOBJ_EQ(fromjson("{$_internalUnpackBucket: { include: ['x'], timeField: 'time', " + "metaField: 'myMeta', bucketMaxSpanSeconds: 3600}}"), + serialized[0]); + ASSERT_BSONOBJ_EQ(fromjson("{$addFields: {newMeta: '$myMeta'}}"), serialized[1]); + } + + // Similar test except the dependency is on an excluded non-meta field. + { + auto unpackSpecObj = fromjson( + "{$_internalUnpackBucket: { exclude: [], timeField: 'time', metaField: 'myMeta', " + "bucketMaxSpanSeconds: 3600}}"); + auto projectSpecObj = fromjson("{$project: {x: true, _id: false}}"); + auto addFieldsSpec = fromjson("{$addFields: {newMeta: '$excluded'}}"); + + auto pipeline = + Pipeline::parse(makeVector(unpackSpecObj, projectSpecObj, addFieldsSpec), getExpCtx()); + + pipeline->optimizePipeline(); + + // We should internalize the $project but _not_ push down the $addFields because it's field + // dependency has been excluded. Theoretically we could remove the $addFields for this + // trivial except but not always. + auto serialized = pipeline->serializeToBson(); + ASSERT_EQ(2u, serialized.size()); + ASSERT_BSONOBJ_EQ(fromjson("{$_internalUnpackBucket: { include: ['x'], timeField: 'time', " + "metaField: 'myMeta', bucketMaxSpanSeconds: 3600}}"), + serialized[0]); + ASSERT_BSONOBJ_EQ(fromjson("{$addFields: {newMeta: '$excluded'}}"), serialized[1]); + } +} + TEST_F(OptimizePipeline, PushdownSortAndAddFields) { auto unpackSpecObj = fromjson( "{$_internalUnpackBucket: { exclude: [], timeField: 'time', metaField: 'myMeta', " |