diff options
author | Alya Berciu <alyacarina@gmail.com> | 2021-03-18 15:42:16 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-03-31 13:24:16 +0000 |
commit | 7142cc2a3dfb59212836a6184f4f6c0e6385f104 (patch) | |
tree | 2bab28e0df1df7a494e26d4a29db9e5d32a83954 /src/mongo/db/matcher/expression_algo.cpp | |
parent | c87f63d4682eaa7d2a7e223050027bc8dd24c810 (diff) | |
download | mongo-7142cc2a3dfb59212836a6184f4f6c0e6385f104.tar.gz |
SERVER-39938: Pushdown $match on $expr before $lookup
Diffstat (limited to 'src/mongo/db/matcher/expression_algo.cpp')
-rw-r--r-- | src/mongo/db/matcher/expression_algo.cpp | 71 |
1 files changed, 36 insertions, 35 deletions
diff --git a/src/mongo/db/matcher/expression_algo.cpp b/src/mongo/db/matcher/expression_algo.cpp index 2f06021a775..11a280eb9ad 100644 --- a/src/mongo/db/matcher/expression_algo.cpp +++ b/src/mongo/db/matcher/expression_algo.cpp @@ -224,22 +224,6 @@ bool _isSubsetOf(const MatchExpression* lhs, const ExistsMatchExpression* rhs) { } /** - * Returns whether the leaf at 'path' is independent of 'fields'. - */ -bool isLeafIndependentOf(const StringData& path, const std::set<std::string>& fields) { - // For each field in 'fields', we need to check if that field is a prefix of 'path' or if 'path' - // is a prefix of that field. For example, the expression {a.b: {c: 1}} is not independent of - // 'a.b.c', and and the expression {a.b.c.d: 1} is not independent of 'a.b.c'. - for (StringData field : fields) { - if (path == field || expression::isPathPrefixOf(path, field) || - expression::isPathPrefixOf(field, path)) { - return false; - } - } - return true; -} - -/** * Creates a MatchExpression that is equivalent to {$and: [children[0], children[1]...]}. */ unique_ptr<MatchExpression> createAndOfNodes(std::vector<unique_ptr<MatchExpression>>* children) { @@ -410,32 +394,49 @@ bool isSubsetOf(const MatchExpression* lhs, const MatchExpression* rhs) { return false; } -bool isIndependentOf(const MatchExpression& expr, const std::set<std::string>& pathSet) { - switch (expr.getCategory()) { - case MatchExpression::MatchCategory::kLogical: { - // Any logical expression is independent of 'pathSet' if all its children are - // independent of 'pathSet'. - for (size_t i = 0; i < expr.numChildren(); i++) { - if (!isIndependentOf(*expr.getChild(i), pathSet)) { - return false; - } +// Checks if 'expr' has any children which do not have renaming implemented. +bool hasOnlyRenameableMatchExpressionChildren(const MatchExpression& expr) { + if (expr.matchType() == MatchExpression::MatchType::EXPRESSION) { + return true; + } else if (expr.getCategory() == MatchExpression::MatchCategory::kArrayMatching || + expr.getCategory() == MatchExpression::MatchCategory::kOther) { + return false; + } else if (expr.getCategory() == MatchExpression::MatchCategory::kLogical) { + for (size_t i = 0; i < expr.numChildren(); i++) { + if (!hasOnlyRenameableMatchExpressionChildren(*expr.getChild(i))) { + return false; } - return true; - } - case MatchExpression::MatchCategory::kLeaf: { - return isLeafIndependentOf(expr.path(), pathSet); - } - // All other match expressions are never considered independent. - case MatchExpression::MatchCategory::kArrayMatching: - case MatchExpression::MatchCategory::kOther: { - return false; } } + return true; +} - MONGO_UNREACHABLE; +bool isIndependentOf(const MatchExpression& expr, const std::set<std::string>& pathSet) { + // Any expression types that do not have renaming implemented cannot have their independence + // evaluated here. See applyRenamesToExpression(). + if (!hasOnlyRenameableMatchExpressionChildren(expr)) { + return false; + } + + auto depsTracker = DepsTracker{}; + expr.addDependencies(&depsTracker); + return std::none_of( + depsTracker.fields.begin(), depsTracker.fields.end(), [&pathSet](auto&& field) { + return pathSet.find(field) != pathSet.end() || + std::any_of(pathSet.begin(), pathSet.end(), [&field](auto&& path) { + return expression::isPathPrefixOf(field, path) || + expression::isPathPrefixOf(path, field); + }); + }); } bool isOnlyDependentOn(const MatchExpression& expr, const std::set<std::string>& roots) { + // Any expression types that do not have renaming implemented cannot have their independence + // evaluated here. See applyRenamesToExpression(). + if (!hasOnlyRenameableMatchExpressionChildren(expr)) { + return false; + } + auto depsTracker = DepsTracker{}; expr.addDependencies(&depsTracker); return std::all_of( |