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

XMLWordPrintableJSON

    • Catalog and Routing
    • ALL
    • Hide
      // Documents containing the min value of a moveChunk will 
      // get lost on a chunk migration.
      
      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();
      
      // Documents that don't contain the shardKey may get 
      // lost due to chunk migrations.
      
      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.shard0.shardName}));
      
      const experimentColl = shardedDb.experimentColl;
      
      assert(experimentColl.drop())
      assert.commandWorked(
          experimentColl.insert([{"_id": 0, "x": 0}, {"_id": 1, "b": 10}, {"_id": 2, "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
      assert.commandWorked(experimentColl.createIndex({b: 1, 'a.$**': 1}));
      assert(s.adminCommand({shardcollection: "test.experimentColl", key: {b: 1}}));
      
      assert(s.adminCommand({
          moveRange: "test.experimentColl",
          min: {b: MinKey},
          max: {b: MaxKey},
          toShard: s.shard1.shardName,
      }));
      
      const results = experimentColl.aggregate([]).toArray()
      assert.eq(results.length, 3);
      // finds 2 documents instead of 3
      
      s.stop();
      
      Show
      // Documents containing the min value of a moveChunk will // get lost on a chunk migration. 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(); // Documents that don't contain the shardKey may get // lost due to chunk migrations. 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.shard0.shardName})); const experimentColl = shardedDb.experimentColl; assert (experimentColl.drop()) assert .commandWorked( experimentColl.insert([{ "_id" : 0, "x" : 0}, { "_id" : 1, "b" : 10}, { "_id" : 2, "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 assert .commandWorked(experimentColl.createIndex({b: 1, 'a.$**' : 1})); assert (s.adminCommand({shardcollection: "test.experimentColl" , key: {b: 1}})); assert (s.adminCommand({ moveRange: "test.experimentColl" , min: {b: MinKey}, max: {b: MaxKey}, toShard: s.shard1.shardName, })); const results = experimentColl.aggregate([]).toArray() assert .eq(results.length, 3); // finds 2 documents instead of 3 s.stop();
    • CAR Team 2025-09-01, CAR Team 2025-09-15
    • 🟥 DDL
    • 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:
            Silvia Surroca
            Reporter:
            Matt Boros
            Votes:
            0 Vote for this issue
            Watchers:
            20 Start watching this issue

              Created:
              Updated: