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

Disallow compound wildcard indexes from being used as a shard key index

    • Query Optimization
    • ALL
    • Hide
      import {ShardingTest} from "jstests/libs/shardingtest.js";
      
      let s = new ShardingTest({name: "experimentColl", shards: 2, mongos: 1});
      let shardedDb = s.getDB("test");
      assert(s.adminCommand({enablesharding: "test", primaryShard: s.shard1.shardName}));
      
      const experimentColl = shardedDb.experimentColl;
      
      assert(experimentColl.drop())
      assert.commandWorked(experimentColl.insert([
      	{
      		"_id" : 0,
      		"a" : 0,
      		"b" : 0
      	},
      	{
      		"_id" : 1,
      		"a" : 0,
      		"b" : 10
      	},
      	{
      		"_id" : 2,
      		"a" : 0,
      		"b" : -10
      	}
      ]))
      
      // We should have 3 documents
      const resultsBeforeSharding = experimentColl.aggregate([]).toArray();
      assert.eq(resultsBeforeSharding.length, 3)
      
      // Shard with a wildcard component in the index
      // Another index that repros the issue is {b: 1, '$**': -1} with {wildcardProjection: {a: 1}}
      assert.commandWorked(experimentColl.createIndex({b: 1, 'a.$**': -1}));
      assert(s.adminCommand({shardcollection: "test.experimentColl", key: {b: 1}}));
      
      // Now split the and move the data between the shards
      assert(s.adminCommand({split: "test.experimentColl", middle: {b: 0}}));
      assert(s.adminCommand({
          moveChunk: "test.experimentColl",
          find: {b: 1},
          to: s.getOther(s.getPrimaryShard("test")).name,
          _waitForDelete: true
      }));
      
      
      const results = experimentColl.aggregate([]).toArray()
      assert.eq(results.length, 3);
      // finds 2 documents instead of 3
      
      s.stop();
      
      Show
      import {ShardingTest} from "jstests/libs/shardingtest.js" ; let s = new ShardingTest({name: "experimentColl" , shards: 2, mongos: 1}); let shardedDb = s.getDB( "test" ); assert (s.adminCommand({enablesharding: "test" , primaryShard: s.shard1.shardName})); const experimentColl = shardedDb.experimentColl; assert (experimentColl.drop()) assert .commandWorked(experimentColl.insert([ { "_id" : 0, "a" : 0, "b" : 0 }, { "_id" : 1, "a" : 0, "b" : 10 }, { "_id" : 2, "a" : 0, "b" : -10 } ])) // We should have 3 documents const resultsBeforeSharding = experimentColl.aggregate([]).toArray(); assert .eq(resultsBeforeSharding.length, 3) // Shard with a wildcard component in the index // Another index that repros the issue is {b: 1, '$**' : -1} with {wildcardProjection: {a: 1}} assert .commandWorked(experimentColl.createIndex({b: 1, 'a.$**' : -1})); assert (s.adminCommand({shardcollection: "test.experimentColl" , key: {b: 1}})); // Now split the and move the data between the shards assert (s.adminCommand({split: "test.experimentColl" , middle: {b: 0}})); assert (s.adminCommand({ moveChunk: "test.experimentColl" , find: {b: 1}, to: s.getOther(s.getPrimaryShard( "test" )).name, _waitForDelete: true })); const results = experimentColl.aggregate([]).toArray() assert .eq(results.length, 3); // finds 2 documents instead of 3 s.stop();
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Some compound wildcard indexes can be used as the shard key index, when this is not supported and can lead to severe correctness issues. We should add validation to prevent this.

      In the repro attached, we see that when a collection is sharded and the shard key index has a wildcard component, documents can be missed in a full collection scan plan.

            Assignee:
            Unassigned Unassigned
            Reporter:
            matt.boros@mongodb.com Matt Boros
            Votes:
            0 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated: