0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

SERVER-40090 DISTINCT_SCAN is only used when certain format of $group _id is specified

This commit is contained in:
Katherine Wu 2020-06-24 10:41:45 -04:00 committed by Evergreen Agent
parent b2869d11c9
commit 20c0cc8c93
2 changed files with 25 additions and 3 deletions

View File

@ -543,6 +543,18 @@ assertResultsMatchWithAndWithoutHintandIndexes(pipeline, [{_id: 1}, {_id: 2}, {_
explain = coll.explain().aggregate(pipeline);
assert.eq(null, getAggPlanStage(explain, "DISTINCT_SCAN"), explain);
//
// Verify that a $sort-$group pipeline with a $first accumulator can use DISTINCT_SCAN, even when
// the group _id field is a singleton object instead of a fieldPath.
//
pipeline = [{$sort: {a: 1, b: 1}}, {$group: {_id: {v: "$a"}, accum: {$first: "$b"}}}];
assertResultsMatchWithAndWithoutHintandIndexes(
pipeline, [{_id: {v: null}, accum: null}, {_id: {v: 1}, accum: 1}, {_id: {v: 2}, accum: 2}]);
explain = coll.explain().aggregate(pipeline);
assert.neq(null, getAggPlanStage(explain, "DISTINCT_SCAN"), explain);
assert.eq({a: 1, b: 1, c: 1}, getAggPlanStage(explain, "DISTINCT_SCAN").keyPattern);
assert.eq(null, getAggPlanStage(explain, "SORT"), explain);
////////////////////////////////////////////////////////////////////////////////////////////////
// We execute all the collation-related tests three times with three different configurations
// (no index, index without collation, index with collation).

View File

@ -762,12 +762,11 @@ bool DocumentSourceGroup::canRunInParallelBeforeWriteStage(
std::unique_ptr<GroupFromFirstDocumentTransformation>
DocumentSourceGroup::rewriteGroupAsTransformOnFirstDocument() const {
if (!_idFieldNames.empty()) {
if (_idExpressions.size() != 1) {
// This transformation is only intended for $group stages that group on a single field.
return nullptr;
}
invariant(_idExpressions.size() == 1);
auto fieldPathExpr = dynamic_cast<ExpressionFieldPath*>(_idExpressions.front().get());
if (!fieldPathExpr || !fieldPathExpr->isRootFieldPath()) {
return nullptr;
@ -794,7 +793,18 @@ DocumentSourceGroup::rewriteGroupAsTransformOnFirstDocument() const {
}
std::vector<std::pair<std::string, boost::intrusive_ptr<Expression>>> fields;
fields.push_back(std::make_pair("_id", ExpressionFieldPath::create(pExpCtx.get(), groupId)));
boost::intrusive_ptr<Expression> idField;
// The _id field can be specified either as a fieldpath (ex. _id: "$a") or as a singleton
// object (ex. _id: {v: "$a"}).
if (_idFieldNames.empty()) {
idField = ExpressionFieldPath::create(pExpCtx.get(), groupId);
} else {
invariant(_idFieldNames.size() == 1);
idField = ExpressionObject::create(pExpCtx.get(),
{{_idFieldNames.front(), _idExpressions.front()}});
}
fields.push_back(std::make_pair("_id", idField));
for (auto&& accumulator : _accumulatedFields) {
fields.push_back(std::make_pair(accumulator.fieldName, accumulator.expr.argument));