summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/indexability.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/indexability.h')
-rw-r--r--src/mongo/db/query/indexability.h204
1 files changed, 100 insertions, 104 deletions
diff --git a/src/mongo/db/query/indexability.h b/src/mongo/db/query/indexability.h
index f1f25ced1c6..a68bf3f328a 100644
--- a/src/mongo/db/query/indexability.h
+++ b/src/mongo/db/query/indexability.h
@@ -32,127 +32,123 @@
namespace mongo {
+/**
+ * Logic for how indices can be used with an expression.
+ */
+class Indexability {
+public:
/**
- * Logic for how indices can be used with an expression.
+ * Is an index over me->path() useful?
+ * This is the same thing as being sargable, if you have a RDBMS background.
*/
- class Indexability {
- public:
- /**
- * Is an index over me->path() useful?
- * This is the same thing as being sargable, if you have a RDBMS background.
- */
- static bool nodeCanUseIndexOnOwnField(const MatchExpression* me) {
- if (me->path().empty()) {
- return false;
- }
-
- if (arrayUsesIndexOnOwnField(me)) {
- return true;
- }
+ static bool nodeCanUseIndexOnOwnField(const MatchExpression* me) {
+ if (me->path().empty()) {
+ return false;
+ }
- return isIndexOnOwnFieldTypeNode(me);
+ if (arrayUsesIndexOnOwnField(me)) {
+ return true;
}
- /**
- * This array operator doesn't have any children with fields and can use an index.
- *
- * Example: a: {$elemMatch: {$gte: 1, $lte: 1}}.
- */
- static bool arrayUsesIndexOnOwnField(const MatchExpression* me) {
- if (!me->isArray()) {
- return false;
- }
+ return isIndexOnOwnFieldTypeNode(me);
+ }
- if (MatchExpression::ELEM_MATCH_VALUE != me->matchType()) {
- return false;
- }
+ /**
+ * This array operator doesn't have any children with fields and can use an index.
+ *
+ * Example: a: {$elemMatch: {$gte: 1, $lte: 1}}.
+ */
+ static bool arrayUsesIndexOnOwnField(const MatchExpression* me) {
+ if (!me->isArray()) {
+ return false;
+ }
+
+ if (MatchExpression::ELEM_MATCH_VALUE != me->matchType()) {
+ return false;
+ }
- // We have an ELEM_MATCH_VALUE expression. In order to be
- // considered "indexable" all children of the ELEM_MATCH_VALUE
- // must be "indexable" type expressions as well.
- for (size_t i = 0; i < me->numChildren(); i++) {
- MatchExpression* child = me->getChild(i);
-
- // Special case for NOT: If the child is a NOT, then it's the thing below
- // the NOT that we care about.
- if (MatchExpression::NOT == child->matchType()) {
- MatchExpression* notChild = child->getChild(0);
-
- if (MatchExpression::MOD == notChild->matchType() ||
- MatchExpression::REGEX == notChild->matchType() ||
- MatchExpression::TYPE_OPERATOR == notChild->matchType()) {
- // We can't index negations of this kind of expression node.
- return false;
- }
-
- // It's the child of the NOT that we check for indexability.
- if (!isIndexOnOwnFieldTypeNode(notChild)) {
- return false;
- }
-
- // Special handling for NOT has already been done; don't fall through.
- continue;
+ // We have an ELEM_MATCH_VALUE expression. In order to be
+ // considered "indexable" all children of the ELEM_MATCH_VALUE
+ // must be "indexable" type expressions as well.
+ for (size_t i = 0; i < me->numChildren(); i++) {
+ MatchExpression* child = me->getChild(i);
+
+ // Special case for NOT: If the child is a NOT, then it's the thing below
+ // the NOT that we care about.
+ if (MatchExpression::NOT == child->matchType()) {
+ MatchExpression* notChild = child->getChild(0);
+
+ if (MatchExpression::MOD == notChild->matchType() ||
+ MatchExpression::REGEX == notChild->matchType() ||
+ MatchExpression::TYPE_OPERATOR == notChild->matchType()) {
+ // We can't index negations of this kind of expression node.
+ return false;
}
- if (!isIndexOnOwnFieldTypeNode(child)) {
+ // It's the child of the NOT that we check for indexability.
+ if (!isIndexOnOwnFieldTypeNode(notChild)) {
return false;
}
+
+ // Special handling for NOT has already been done; don't fall through.
+ continue;
}
- // The entire ELEM_MATCH_VALUE is indexable since every one of its children
- // is indexable.
- return true;
+ if (!isIndexOnOwnFieldTypeNode(child)) {
+ return false;
+ }
}
- /**
- * Certain array operators require that the field for that operator is prepended
- * to all fields in that operator's children.
- *
- * Example: a: {$elemMatch: {b:1, c:1}}.
- */
- static bool arrayUsesIndexOnChildren(const MatchExpression* me) {
- return me->isArray() && MatchExpression::ELEM_MATCH_OBJECT == me->matchType();
- }
+ // The entire ELEM_MATCH_VALUE is indexable since every one of its children
+ // is indexable.
+ return true;
+ }
- /**
- * Returns true if 'me' is a NOT, and the child of the NOT can use
- * an index on its own field.
- */
- static bool isBoundsGeneratingNot(const MatchExpression* me) {
- return MatchExpression::NOT == me->matchType() &&
- nodeCanUseIndexOnOwnField(me->getChild(0));
- }
+ /**
+ * Certain array operators require that the field for that operator is prepended
+ * to all fields in that operator's children.
+ *
+ * Example: a: {$elemMatch: {b:1, c:1}}.
+ */
+ static bool arrayUsesIndexOnChildren(const MatchExpression* me) {
+ return me->isArray() && MatchExpression::ELEM_MATCH_OBJECT == me->matchType();
+ }
- /**
- * Returns true if either 'me' is a bounds generating NOT,
- * or 'me' can use an index on its own field.
- */
- static bool isBoundsGenerating(const MatchExpression* me) {
- return isBoundsGeneratingNot(me) || nodeCanUseIndexOnOwnField(me);
- }
+ /**
+ * Returns true if 'me' is a NOT, and the child of the NOT can use
+ * an index on its own field.
+ */
+ static bool isBoundsGeneratingNot(const MatchExpression* me) {
+ return MatchExpression::NOT == me->matchType() &&
+ nodeCanUseIndexOnOwnField(me->getChild(0));
+ }
- private:
- /**
- * Returns true if 'me' is "sargable" but is not a negation and
- * is not an array node such as ELEM_MATCH_VALUE.
- *
- * Used as a helper for nodeCanUseIndexOnOwnField().
- */
- static bool isIndexOnOwnFieldTypeNode(const MatchExpression* me) {
- return me->matchType() == MatchExpression::LTE
- || me->matchType() == MatchExpression::LT
- || me->matchType() == MatchExpression::EQ
- || me->matchType() == MatchExpression::GT
- || me->matchType() == MatchExpression::GTE
- || me->matchType() == MatchExpression::REGEX
- || me->matchType() == MatchExpression::MOD
- || me->matchType() == MatchExpression::MATCH_IN
- || me->matchType() == MatchExpression::TYPE_OPERATOR
- || me->matchType() == MatchExpression::GEO
- || me->matchType() == MatchExpression::GEO_NEAR
- || me->matchType() == MatchExpression::EXISTS
- || me->matchType() == MatchExpression::TEXT;
- }
- };
+ /**
+ * Returns true if either 'me' is a bounds generating NOT,
+ * or 'me' can use an index on its own field.
+ */
+ static bool isBoundsGenerating(const MatchExpression* me) {
+ return isBoundsGeneratingNot(me) || nodeCanUseIndexOnOwnField(me);
+ }
+
+private:
+ /**
+ * Returns true if 'me' is "sargable" but is not a negation and
+ * is not an array node such as ELEM_MATCH_VALUE.
+ *
+ * Used as a helper for nodeCanUseIndexOnOwnField().
+ */
+ static bool isIndexOnOwnFieldTypeNode(const MatchExpression* me) {
+ return me->matchType() == MatchExpression::LTE || me->matchType() == MatchExpression::LT ||
+ me->matchType() == MatchExpression::EQ || me->matchType() == MatchExpression::GT ||
+ me->matchType() == MatchExpression::GTE || me->matchType() == MatchExpression::REGEX ||
+ me->matchType() == MatchExpression::MOD ||
+ me->matchType() == MatchExpression::MATCH_IN ||
+ me->matchType() == MatchExpression::TYPE_OPERATOR ||
+ me->matchType() == MatchExpression::GEO ||
+ me->matchType() == MatchExpression::GEO_NEAR ||
+ me->matchType() == MatchExpression::EXISTS || me->matchType() == MatchExpression::TEXT;
+ }
+};
} // namespace mongo