diff options
author | Kevin Cherkauer <kevin.cherkauer@mongodb.com> | 2023-02-10 22:25:37 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-03-17 17:25:03 +0000 |
commit | d21c7305f5da8f58a93c5d5910a5b04e6a56c85d (patch) | |
tree | 6d0439d465354710dd66fcae20968348e7f7cc3f /src | |
parent | 5f2b3207b0801fe59988f9d8b3b19ae8734ff9ba (diff) | |
download | mongo-d21c7305f5da8f58a93c5d5910a5b04e6a56c85d.tar.gz |
SERVER-73822 Time-series $group rewrite ignores certain accumulators
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp | 14 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/group_reorder_test.cpp | 27 |
2 files changed, 35 insertions, 6 deletions
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 79dafdb4618..0f5d37b2c27 100644 --- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp +++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp @@ -939,10 +939,10 @@ DocumentSourceInternalUnpackBucket::rewriteGroupByMinMax(Pipeline::SourceContain return {}; } - if (!_bucketUnpacker.bucketSpec().metaField()) { + if (!_bucketUnpacker.bucketSpec().metaField) { return {}; } - const auto& metaField = *_bucketUnpacker.bucketSpec().metaField(); + const auto& metaField = *_bucketUnpacker.bucketSpec().metaField; const auto& idFields = groupPtr->getIdFields(); if (idFields.size() != 1) { @@ -971,7 +971,7 @@ DocumentSourceInternalUnpackBucket::rewriteGroupByMinMax(Pipeline::SourceContain } const auto& rootFieldName = path.getFieldName(1); - if (rootFieldName == _bucketUnpacker.bucketSpec().timeField()) { + if (rootFieldName == _bucketUnpacker.bucketSpec().timeField) { // Rewrite not valid for time field. We want to eliminate the bucket // unpack stage here. return {}; @@ -987,10 +987,10 @@ DocumentSourceInternalUnpackBucket::rewriteGroupByMinMax(Pipeline::SourceContain } } else { // Update aggregates to reference the control field. - const auto op = stmt.expr.name; - if (op == "$min") { + const auto op = stmt.makeAccumulator()->getOpName(); + if (op == "$min"_sd) { os << timeseries::kControlMinFieldNamePrefix; - } else if (op == "$max") { + } else if (op == "$max"_sd) { os << timeseries::kControlMaxFieldNamePrefix; } else { // Rewrite is valid only for min and max aggregates. @@ -1011,6 +1011,8 @@ DocumentSourceInternalUnpackBucket::rewriteGroupByMinMax(Pipeline::SourceContain AccumulationExpression accExpr = stmt.expr; accExpr.argument = newExpr; accumulationStatements.emplace_back(stmt.fieldName, std::move(accExpr)); + } else { + return {}; } } diff --git a/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/group_reorder_test.cpp b/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/group_reorder_test.cpp index 6100897fd79..6dbc68d3616 100644 --- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/group_reorder_test.cpp +++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/group_reorder_test.cpp @@ -94,6 +94,33 @@ TEST_F(InternalUnpackBucketGroupReorder, MinMaxGroupOnMetadata) { ASSERT_BSONOBJ_EQ(optimized, serialized[0]); } +// Test SERVER-73822 fix: complex $min and $max (i.e. not just straight field refs) work correctly. +TEST_F(InternalUnpackBucketGroupReorder, MinMaxComplexGroupOnMetadata) { + auto unpackSpecObj = fromjson( + "{$_internalUnpackBucket: { include: ['a', 'b', 'c'], metaField: 'meta1', timeField: 't', " + "bucketMaxSpanSeconds: 3600}}"); + auto groupSpecObj = fromjson( + "{$group: {_id: '$meta1.a.b', accmin: {$min: {$add: ['$b', {$const: 0}]}}, accmax: {$max: " + "{$add: [{$const: 0}, '$c']}}}}"); + + auto pipeline = Pipeline::parse(makeVector(unpackSpecObj, groupSpecObj), getExpCtx()); + pipeline->optimizePipeline(); + + auto serialized = pipeline->serializeToBson(); + ASSERT_EQ(2, serialized.size()); + + // Order of fields may be different from the original stage. + auto unpackSpecResultObj = fromjson( + "{$_internalUnpackBucket: { include: ['a', 'b', 'c'], timeField: 't', metaField: 'meta1', " + "bucketMaxSpanSeconds: 3600}}"); + ASSERT_BSONOBJ_EQ(unpackSpecResultObj, serialized[0]); + + auto groupSpecOutputObj = fromjson( + "{$group: {_id: '$meta1.a.b', accmin: {$min: {$add: ['$b', {$const: 0}]}}, accmax: {$max: " + "{$add: ['$c', {$const: 0}]}}}}"); + ASSERT_BSONOBJ_EQ(groupSpecOutputObj, serialized[1]); +} + TEST_F(InternalUnpackBucketGroupReorder, MinMaxGroupOnMetafield) { auto unpackSpecObj = fromjson( "{$_internalUnpackBucket: { include: ['a', 'b', 'c'], metaField: 'meta1', timeField: 't', " |