diff options
author | joshua <80741223+jlap199@users.noreply.github.com> | 2022-09-23 22:45:01 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-09-23 23:18:32 +0000 |
commit | 05cda545eb5d1911753cbd3c8004aac9308d890c (patch) | |
tree | be8a8479ec486e97e32172946c50801e71e5c7cf /src | |
parent | 6552887793ccf7dc0c52ff7e19167f10990b6567 (diff) | |
download | mongo-05cda545eb5d1911753cbd3c8004aac9308d890c.tar.gz |
SERVER-68115 Do not drop empty path component from elemMatch path during index selection
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/query/planner_ixselect.cpp | 20 |
1 files changed, 6 insertions, 14 deletions
diff --git a/src/mongo/db/query/planner_ixselect.cpp b/src/mongo/db/query/planner_ixselect.cpp index 9e52daeb6ea..bb7c7cec186 100644 --- a/src/mongo/db/query/planner_ixselect.cpp +++ b/src/mongo/db/query/planner_ixselect.cpp @@ -257,15 +257,11 @@ void QueryPlannerIXSelect::getFields(const MatchExpression* node, // Leaf nodes with a path and some array operators. if (Indexability::nodeCanUseIndexOnOwnField(node)) { out->insert(prefix + node->path().toString()); - } else if (Indexability::arrayUsesIndexOnChildren(node)) { + } else if (Indexability::arrayUsesIndexOnChildren(node) && !node->path().empty()) { // If the array uses an index on its children, it's something like // {foo : {$elemMatch: {bar: 1}}}, in which case the predicate is really over foo.bar. - // - // When we have {foo: {$all: [{$elemMatch: {a: 1}}], the path of the embedded elemMatch - // is empty. We don't want to append a dot in that case as the field would be foo..a. - if (!node->path().empty()) { - prefix += node->path().toString() + "."; - } + // Note we skip empty path components since they are not allowed in index key patterns. + prefix += node->path().toString() + "."; for (size_t i = 0; i < node->numChildren(); ++i) { getFields(node->getChild(i), prefix, out); @@ -783,7 +779,8 @@ void QueryPlannerIXSelect::_rateIndices(MatchExpression* node, childRt->path = rt->path; node->getChild(0)->setTag(childRt); } - } else if (Indexability::arrayUsesIndexOnChildren(node)) { + } else if (Indexability::arrayUsesIndexOnChildren(node) && !node->path().empty()) { + // Note we skip empty path components since they are not allowed in index key patterns. const auto newPath = prefix + node->path().toString(); ElemMatchContext newContext; // Note this StringData is unowned and references the string declared on the stack here. @@ -794,12 +791,7 @@ void QueryPlannerIXSelect::_rateIndices(MatchExpression* node, // If the array uses an index on its children, it's something like // {foo: {$elemMatch: {bar: 1}}}, in which case the predicate is really over foo.bar. - // - // When we have {foo: {$all: [{$elemMatch: {a: 1}}], the path of the embedded elemMatch - // is empty. We don't want to append a dot in that case as the field would be foo..a. - if (!node->path().empty()) { - prefix += node->path().toString() + "."; - } + prefix += node->path().toString() + "."; for (size_t i = 0; i < node->numChildren(); ++i) { _rateIndices(node->getChild(i), prefix, indices, collator, newContext); } |