[SERVER-18308] Partial indexes should support point queries over single field ranges Created: 04/May/15  Updated: 14/Apr/16  Resolved: 14/May/15

Status: Closed
Project: Core Server
Component/s: Querying
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Max Hirschhorn Assignee: Max Hirschhorn
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to SERVER-17858 Partial indexes should support more c... Closed
Backwards Compatibility: Fully Compatible
Operating System: ALL
Steps To Reproduce:

db.foo.ensureIndex({a:1}, {filter:{a:{$gt:5, $lt:10}}})
db.foo.insert({a:6})

Sprint: Quint Iteration 3
Participants:

 Description   

The code only checks whether an AND-expression filter is satisfied if the query is also an AND-expression. This means that querying for an explicit value of a will not be able to use the partial index.

> db.foo.find({a:6}).explain().queryPlanner
{
  "plannerVersion" : 1,
  "namespace" : "test.foo",
  "indexFilterSet" : false,
  "parsedQuery" : {
    "a" : {
      "$eq" : 6
    }
  },
  "winningPlan" : {
    "stage" : "COLLSCAN",
    "filter" : {
      "a" : {
        "$eq" : 6
      }
    },
    "direction" : "forward"
  },
  "rejectedPlans" : [ ]
}

But specifying a fake AND-expression in the query will allow the partial index to be used.

> db.foo.find({$and: [{a:6}, {a:6}]}).explain().queryPlanner
{
  "plannerVersion" : 1,
  "namespace" : "test.foo",
  "indexFilterSet" : false,
  "parsedQuery" : {
    "$and" : [
      {
        "a" : {
          "$eq" : 6
        }
      },
      {
        "a" : {
          "$eq" : 6
        }
      }
    ]
  },
  "winningPlan" : {
    "stage" : "FETCH",
    "inputStage" : {
      "stage" : "IXSCAN",
      "keyPattern" : {
        "a" : 1
      },
      "indexName" : "a_1",
      "isMultiKey" : false,
      "indexVersion" : 1,
      "direction" : "forward",
      "indexBounds" : {
        "a" : [
          "[6.0, 6.0]"
        ]
      }
    }
  },
  "rejectedPlans" : [ ]
}



 Comments   
Comment by Max Hirschhorn [ 14/May/15 ]

Resolved as part of SERVER-18350 by moving the handling for rhs->matchType() == MatchExpression::AND outside of the check that lhs->matchType() == MatchExpression::AND. A point query lhs will not be an AND-expression, although it can still answer a partial index filter that is one.

Converted the reproduction steps described here to a test case in expression_algo_test.cpp.

TEST(ExpressionAlgoIsSubsetOf, PointInBoundedRange) {
    ParsedMatchExpression filter("{a: {$gt: 5, $lt: 10}}");
    ParsedMatchExpression query("{a: 6}");
 
    ASSERT_TRUE(expression::isSubsetOf(query.get(), filter.get()));
    ASSERT_FALSE(expression::isSubsetOf(filter.get(), query.get()));
}
 
TEST(ExpressionAlgoIsSubsetOf, PointInBoundedRange_FakeAnd) {
    ParsedMatchExpression filter("{a: {$gt: 5, $lt: 10}}");
    ParsedMatchExpression query("{$and: [{a: 6}, {a: 6}]}");
 
    ASSERT_TRUE(expression::isSubsetOf(query.get(), filter.get()));
    ASSERT_FALSE(expression::isSubsetOf(filter.get(), query.get()));
}

Generated at Thu Feb 08 03:47:15 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.