summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/planner_ixselect.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/planner_ixselect.cpp')
-rw-r--r--src/mongo/db/query/planner_ixselect.cpp29
1 files changed, 19 insertions, 10 deletions
diff --git a/src/mongo/db/query/planner_ixselect.cpp b/src/mongo/db/query/planner_ixselect.cpp
index 3443ba16581..4aa69cfce17 100644
--- a/src/mongo/db/query/planner_ixselect.cpp
+++ b/src/mongo/db/query/planner_ixselect.cpp
@@ -174,12 +174,15 @@ bool QueryPlannerIXSelect::notEqualsNullCanUseIndex(const IndexEntry& index,
}
}
-static double fieldWithDefault(const BSONObj& infoObj, const string& name, double def) {
- BSONElement e = infoObj[name];
- if (e.isNumber()) {
- return e.numberDouble();
- }
- return def;
+bool QueryPlannerIXSelect::canUseIndexForNin(const InMatchExpression* ime) {
+ const std::vector<BSONElement>& inList = ime->getEqualities();
+ auto containsNull = [](const BSONElement& elt) { return elt.type() == jstNULL; };
+ auto containsEmptyArray = [](const BSONElement& elt) {
+ return elt.type() == Array && elt.embeddedObject().isEmpty();
+ };
+ return ime->getRegexes().empty() && inList.size() == 2 &&
+ std::any_of(inList.begin(), inList.end(), containsNull) &&
+ std::any_of(inList.begin(), inList.end(), containsEmptyArray);
}
/**
@@ -432,10 +435,6 @@ bool QueryPlannerIXSelect::_compatible(const BSONElement& keyPatternElt,
return false;
}
- if (isEqualsArrayOrNotInArray(child)) {
- return false;
- }
-
// Most of the time we can't use a multikey index for a $ne: null query, however there
// are a few exceptions around $elemMatch.
const bool canUseIndexForNeNull =
@@ -447,6 +446,12 @@ bool QueryPlannerIXSelect::_compatible(const BSONElement& keyPatternElt,
// If it's a negated $in, it can't have any REGEX's inside.
if (MatchExpression::MATCH_IN == childtype) {
InMatchExpression* ime = static_cast<InMatchExpression*>(node->getChild(0));
+
+ if (canUseIndexForNin(ime)) {
+ // This is a case that we know is supported.
+ return true;
+ }
+
if (!ime->getRegexes().empty()) {
return false;
}
@@ -457,6 +462,10 @@ bool QueryPlannerIXSelect::_compatible(const BSONElement& keyPatternElt,
return false;
}
}
+
+ if (isEqualsArrayOrNotInArray(child)) {
+ return false;
+ }
}
// If this is an $elemMatch value, make sure _all_ of the children can use the index.