Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-92806

Plan cache entry ignores index collation with $elemMatch

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 8.1.0-rc0
    • Affects Version/s: None
    • Component/s: None
    • Query Optimization
    • Fully Compatible
    • ALL
    • v8.0, v7.0, v6.0, v5.0
    • Hide
      const conn = MongoRunner.runMongod();
      const db = conn.getDB(jsTestName());
      
      const documentList = [
          {_id: 47, "obj": {"array": ["lowercase"]}},
          {_id: 78, "obj": {"array": ["lowercase"]}},
      ];
      
      let coll = db.bf34252;
      coll.drop();
      assert.commandWorked(coll.insert(documentList));
      
      // Create two indexes and run the query twice to create an _active_ plan cache entry.
      assert.commandWorked(coll.createIndex({"obj.array": 1}, {
          collation: {locale: 'en'},
      }));
      assert.commandWorked(coll.createIndex({"obj.array": 1, unused: 1}, {
          collation: {locale: 'en'},
      }));
      
      // Sanity check
      const match2 = {"obj.array": {$elemMatch: {$gte: "UPPERCASE"}}};
      assert.eq(2, coll.find(match2).itcount());
      
      for (let i = 0; i < 2; ++i) {
          coll.find({"obj.array": {$elemMatch: {$gte: NumberLong("78219")}}}).itcount();
      }
      
      assert.eq(2, coll.find(match2).itcount()); // <---- THIS ASSERTION FAILS
      
      MongoRunner.stopMongod(conn);
      
      Show
      const conn = MongoRunner.runMongod(); const db = conn.getDB(jsTestName()); const documentList = [ {_id: 47, "obj" : { "array" : [ "lowercase" ]}}, {_id: 78, "obj" : { "array" : [ "lowercase" ]}}, ]; let coll = db.bf34252; coll.drop(); assert.commandWorked(coll.insert(documentList)); // Create two indexes and run the query twice to create an _active_ plan cache entry. assert.commandWorked(coll.createIndex({ "obj.array" : 1}, { collation: {locale: 'en' }, })); assert.commandWorked(coll.createIndex({ "obj.array" : 1, unused: 1}, { collation: {locale: 'en' }, })); // Sanity check const match2 = { "obj.array" : {$elemMatch: {$gte: "UPPERCASE" }}}; assert.eq(2, coll.find(match2).itcount()); for (let i = 0; i < 2; ++i) { coll.find({ "obj.array" : {$elemMatch: {$gte: NumberLong( "78219" )}}}).itcount(); } assert.eq(2, coll.find(match2).itcount()); // <---- THIS ASSERTION FAILS MongoRunner.stopMongod(conn);
    • QO 2024-08-05
    • 200

      The plan cache key should distinguish between two queries with predicates which differ in index compatibility due to index collation. This does not happen when $elemMatch is present in the predicate.

            Assignee:
            hana.pearlman@mongodb.com Hana Pearlman
            Reporter:
            jess.balint@mongodb.com Jess Balint
            Votes:
            0 Vote for this issue
            Watchers:
            11 Start watching this issue

              Created:
              Updated:
              Resolved: