summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorauto-revert-processor <dev-prod-dag@mongodb.com>2022-08-30 09:49:04 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-08-30 10:37:53 +0000
commitbc38590591e0c5509f73482c2431ca28e8f882e8 (patch)
tree931e95bc70d7b5153255ee08787efce99cb1b6b3 /src/mongo
parent81c41bdfdc56f05973fae70e80e80919f18f50c9 (diff)
downloadmongo-bc38590591e0c5509f73482c2431ca28e8f882e8.tar.gz
Revert "SERVER-67780 Incorrect $group rewrite for timeseries collection when the accumulator uses meta field"
This reverts commit ccb0d93033900be8cead29d3cdd414d8a85f2b03.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp109
-rw-r--r--src/mongo/db/pipeline/document_source_internal_unpack_bucket_test/group_reorder_test.cpp16
2 files changed, 52 insertions, 73 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 1729510a154..cfa58471fda 100644
--- a/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp
+++ b/src/mongo/db/pipeline/document_source_internal_unpack_bucket.cpp
@@ -639,70 +639,60 @@ DocumentSourceInternalUnpackBucket::rewriteGroupByMinMax(Pipeline::SourceContain
return {};
}
- if (!_bucketUnpacker.bucketSpec().metaField()) {
- return {};
- }
- const auto& metaField = *_bucketUnpacker.bucketSpec().metaField();
-
const auto& idFields = groupPtr->getIdFields();
- if (idFields.size() != 1) {
+ if (idFields.size() != 1 || !_bucketUnpacker.bucketSpec().metaField().has_value()) {
return {};
}
const auto& exprId = idFields.cbegin()->second;
- // TODO: SERVER-68811. Allow rewrites if expression is constant.
const auto* exprIdPath = dynamic_cast<const ExpressionFieldPath*>(exprId.get());
if (exprIdPath == nullptr) {
return {};
}
const auto& idPath = exprIdPath->getFieldPath();
- if (idPath.getPathLength() < 2 || idPath.getFieldName(1) != metaField) {
+ if (idPath.getPathLength() < 2 ||
+ idPath.getFieldName(1) != _bucketUnpacker.bucketSpec().metaField().value()) {
return {};
}
+ bool suitable = true;
std::vector<AccumulationStatement> accumulationStatements;
for (const AccumulationStatement& stmt : groupPtr->getAccumulatedFields()) {
+ const auto op = stmt.expr.name;
+ const bool isMin = op == "$min";
+ const bool isMax = op == "$max";
+
+ // Rewrite is valid only for min and max aggregates.
+ if (!isMin && !isMax) {
+ suitable = false;
+ break;
+ }
+
const auto* exprArg = stmt.expr.argument.get();
if (const auto* exprArgPath = dynamic_cast<const ExpressionFieldPath*>(exprArg)) {
const auto& path = exprArgPath->getFieldPath();
- if (path.getPathLength() <= 1) {
- return {};
- }
-
- const auto& rootFieldName = path.getFieldName(1);
- if (rootFieldName == _bucketUnpacker.bucketSpec().timeField()) {
+ if (path.getPathLength() <= 1 ||
+ path.getFieldName(1) == _bucketUnpacker.bucketSpec().timeField()) {
// Rewrite not valid for time field. We want to eliminate the bucket
// unpack stage here.
- return {};
+ suitable = false;
+ break;
}
+ // Update aggregates to reference the control field.
std::ostringstream os;
- if (rootFieldName == metaField) {
- // Update aggregates to reference the meta field.
- os << timeseries::kBucketMetaFieldName;
-
- for (size_t index = 2; index < path.getPathLength(); index++) {
- os << "." << path.getFieldName(index);
- }
+ if (isMin) {
+ os << timeseries::kControlMinFieldNamePrefix;
} else {
- // Update aggregates to reference the control field.
- const auto op = stmt.expr.name;
- if (op == "$min") {
- os << timeseries::kControlMinFieldNamePrefix;
- } else if (op == "$max") {
- os << timeseries::kControlMaxFieldNamePrefix;
- } else {
- // Rewrite is valid only for min and max aggregates.
- return {};
- }
+ os << timeseries::kControlMaxFieldNamePrefix;
+ }
- for (size_t index = 1; index < path.getPathLength(); index++) {
- if (index > 1) {
- os << ".";
- }
- os << path.getFieldName(index);
+ for (size_t index = 1; index < path.getPathLength(); index++) {
+ if (index > 1) {
+ os << ".";
}
+ os << path.getFieldName(index);
}
const auto& newExpr = ExpressionFieldPath::createPathFromString(
@@ -714,30 +704,35 @@ DocumentSourceInternalUnpackBucket::rewriteGroupByMinMax(Pipeline::SourceContain
}
}
- std::ostringstream os;
- os << timeseries::kBucketMetaFieldName;
- for (size_t index = 2; index < idPath.getPathLength(); index++) {
- os << "." << idPath.getFieldName(index);
- }
- auto exprId1 = ExpressionFieldPath::createPathFromString(
- pExpCtx.get(), os.str(), pExpCtx->variablesParseState);
+ if (suitable) {
+ std::ostringstream os;
+ os << timeseries::kBucketMetaFieldName;
+ for (size_t index = 2; index < idPath.getPathLength(); index++) {
+ os << "." << idPath.getFieldName(index);
+ }
+ auto exprId1 = ExpressionFieldPath::createPathFromString(
+ pExpCtx.get(), os.str(), pExpCtx->variablesParseState);
- auto newGroup = DocumentSourceGroup::create(pExpCtx,
- std::move(exprId1),
- std::move(accumulationStatements),
- groupPtr->getMaxMemoryUsageBytes());
+ auto newGroup = DocumentSourceGroup::create(pExpCtx,
+ std::move(exprId1),
+ std::move(accumulationStatements),
+ groupPtr->getMaxMemoryUsageBytes());
- // Erase current stage and following group stage, and replace with updated group.
- container->erase(std::next(itr));
- *itr = std::move(newGroup);
+ // Erase current stage and following group stage, and replace with updated
+ // group.
+ container->erase(std::next(itr));
+ *itr = std::move(newGroup);
- if (itr == container->begin()) {
- // Optimize group stage.
- return {true, itr};
- } else {
- // Give chance of the previous stage to optimize against group stage.
- return {true, std::prev(itr)};
+ if (itr == container->begin()) {
+ // Optimize group stage.
+ return {true, itr};
+ } else {
+ // Give chance of the previous stage to optimize against group stage.
+ return {true, std::prev(itr)};
+ }
}
+
+ return {};
}
bool DocumentSourceInternalUnpackBucket::haveComputedMetaField() const {
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..70b524c7510 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,22 +94,6 @@ TEST_F(InternalUnpackBucketGroupReorder, MinMaxGroupOnMetadata) {
ASSERT_BSONOBJ_EQ(optimized, serialized[0]);
}
-TEST_F(InternalUnpackBucketGroupReorder, MinMaxGroupOnMetafield) {
- auto unpackSpecObj = fromjson(
- "{$_internalUnpackBucket: { include: ['a', 'b', 'c'], metaField: 'meta1', timeField: 't', "
- "bucketMaxSpanSeconds: 3600}}");
- auto groupSpecObj = fromjson("{$group: {_id: '$meta1.a.b', accmin: {$sum: '$meta1.f1'}}}");
-
- auto pipeline = Pipeline::parse(makeVector(unpackSpecObj, groupSpecObj), getExpCtx());
- pipeline->optimizePipeline();
-
- auto serialized = pipeline->serializeToBson();
- ASSERT_EQ(1, serialized.size());
-
- auto optimized = fromjson("{$group: {_id: '$meta.a.b', accmin: {$sum: '$meta.f1'}}}");
- ASSERT_BSONOBJ_EQ(optimized, serialized[0]);
-}
-
TEST_F(InternalUnpackBucketGroupReorder, MinMaxGroupOnMetadataNegative) {
auto unpackSpecObj = fromjson(
"{$_internalUnpackBucket: { include: ['a', 'b', 'c'], timeField: 't', metaField: 'meta', "