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

Shards see different values for 'let' parameter when using $rand

    • Query Optimization
    • Fully Compatible
    • ALL
    • Hide

      I wrote the following script to demonstrate the issue:

      (function() {
      "use strict";
      
      const dbName = "test";
      
      const st = new ShardingTest({shards: 2});
      const db = st.s.getDB(dbName);
      
      const coll = db.coll;
      coll.drop();
      
      assert.commandWorked(coll.insert([{x: -2}, {x: 2}]));
      assert.commandWorked(coll.createIndex({x: 1}));
      
      st.shardColl(coll, {x: 1}, {x: 0}, {x: 1});
      
      const findCmd = {
          find: coll.getName(),
          projection: {_id: 0, rand: "$$randVal"},
          let : {randVal: {$rand: {}}}
      };
      let result = assert.commandWorked(db.runCommand(findCmd));
      let batch = result.cursor.firstBatch;
      assert.eq(batch.length, 2, result);
      
      // Assert that both shards see the same pseudo-random value. This assertion fails.
      assert.eq(batch[0].rand, batch[1].rand, result);
      
      st.stop();
      }());
      

      I'm running it locally with a resmoke.py invocation like this:

      python3 buildscripts/resmoke.py run --suites=sharding repro_let_rand.js
      
      Show
      I wrote the following script to demonstrate the issue: (function() { "use strict" ; const dbName = "test" ; const st = new ShardingTest({shards: 2}); const db = st.s.getDB(dbName); const coll = db.coll; coll.drop(); assert .commandWorked(coll.insert([{x: -2}, {x: 2}])); assert .commandWorked(coll.createIndex({x: 1})); st.shardColl(coll, {x: 1}, {x: 0}, {x: 1}); const findCmd = { find: coll.getName(), projection: {_id: 0, rand: "$$randVal" }, let : {randVal: {$rand: {}}} }; let result = assert .commandWorked(db.runCommand(findCmd)); let batch = result.cursor.firstBatch; assert .eq(batch.length, 2, result); // Assert that both shards see the same pseudo-random value. This assertion fails. assert .eq(batch[0].rand, batch[1].rand, result); st.stop(); }()); I'm running it locally with a resmoke.py invocation like this: python3 buildscripts/resmoke.py run --suites=sharding repro_let_rand.js
    • QO 2023-06-26, QO 2023-07-10, QO 2023-07-24, QO 2023-08-07, QO 2023-08-21, QO 2023-09-04, QO 2023-09-18, QO 2023-10-02, QO 2023-10-16

      In SERVER-48905 we extended the let parameters mechanism so that it works in combination with the $rand expression. For example, the following query was made legal by SERVER-48905:

      const findCmd = {
          find: coll.getName(),
          projection: {_id: 0, rand: "$$randVal"},
          let : {randVal: {$rand: {}}}
      };
      

      The intended semantics is that the $rand expression is evaluated just once up front and the result is treated as a constant for the remainder of the execution of the query.

      In sharded contexts, mongos should generate the random number and pass it to the shards so that all shards see the same random number. This is not working as expected. Glancing at the code, it looks like we are sending the full $rand expression to each shard. As a result, each shard generates its own random number. My script in "steps to reproduce" has a full example of the problem.

            Assignee:
            david.percy@mongodb.com David Percy
            Reporter:
            david.storch@mongodb.com David Storch
            Votes:
            0 Vote for this issue
            Watchers:
            10 Start watching this issue

              Created:
              Updated:
              Resolved: