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

Updating multiple elements in an array produces incorrect results

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 3.5.10
    • Affects Version/s: None
    • Component/s: Querying
    • None
    • Fully Compatible
    • ALL
    • Hide
      python buildscripts/resmoke.py repro_server29762.js
      
      repro_server29762.js
      // The featureCompatibilityVersion must be 3.6 in order for the following update to not produce the
      // correct results beause otherwise the UpdateDriver doesn't parse expressions into UpdateNodes.
      // (See SERVER-28762.)
      const res = assert.commandWorked(db.adminCommand({
          getParameter: 1,
          featureCompatibilityVersion: 1,
      }));
      assert.eq("3.6", res.featureCompatibilityVersion);
      
      db.mycoll.drop();
      assert.writeOK(db.mycoll.insert({_id: 0, a: []}));
      
      // Neither {$set: {"a.2": 2, "a.9": 10}} nor {$set: {"a.0": 2, "a.10": 10}} cause the resulting
      // document to become [null, null, ... , null, 10, 2], but the following update does.
      assert.writeOK(db.mycoll.update({_id: 0}, {$set: {"a.2": 2, "a.10": 10}}));
      
      const arrValue = new Array(11).fill(null);
      arrValue[2] = 2;
      arrValue[arrValue.length - 1] = 10;
      assert.eq({_id: 0, a: arrValue}, db.mycoll.findOne({_id: 0}));
      
      Show
      python buildscripts/resmoke.py repro_server29762.js repro_server29762.js // The featureCompatibilityVersion must be 3.6 in order for the following update to not produce the // correct results beause otherwise the UpdateDriver doesn't parse expressions into UpdateNodes. // (See SERVER-28762.) const res = assert.commandWorked(db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1, })); assert.eq( "3.6" , res.featureCompatibilityVersion); db.mycoll.drop(); assert.writeOK(db.mycoll.insert({_id: 0, a: []})); // Neither {$set: { "a.2" : 2, "a.9" : 10}} nor {$set: { "a.0" : 2, "a.10" : 10}} cause the resulting // document to become [ null , null , ... , null , 10, 2], but the following update does. assert.writeOK(db.mycoll.update({_id: 0}, {$set: { "a.2" : 2, "a.10" : 10}})); const arrValue = new Array(11).fill( null ); arrValue[2] = 2; arrValue[arrValue.length - 1] = 10; assert.eq({_id: 0, a: arrValue}, db.mycoll.findOne({_id: 0}));
    • Query 2017-07-10
    • 0

      This appears to be the result of the changes from ab165e7 as part of SERVER-28762 and therefore doesn't affect any released version of MongoDB.

      Additionally, I think it is worth mentioning that this issue was only detected because the update operation produced a different result (i.e. the correct one) when applied by the secondary despite having the same $set modifier.

      {  "ts" : Timestamp(1498018241, 1),  "t" : NumberLong(1),  "h" : NumberLong("-5655460550431900619"),  "v" : 2,  "op" : "c",  "ns" : "test.$cmd",  "wt" : ISODate("2017-06-21T04:10:41.164Z"),  "o" : {  "create" : "mycoll",  "idIndex" : {  "v" : 2,  "key" : {  "_id" : 1 },  "name" : "_id_",  "ns" : "test.mycoll" } } }
      {  "ts" : Timestamp(1498018241, 2),  "t" : NumberLong(1),  "h" : NumberLong("8601612499795829594"),  "v" : 2,  "op" : "i",  "ns" : "test.mycoll",  "wt" : ISODate("2017-06-21T04:10:41.164Z"),  "o" : {  "_id" : 0,  "a" : [ ] } }
      {  "ts" : Timestamp(1498018241, 3),  "t" : NumberLong(1),  "h" : NumberLong("7416058103814577585"),  "v" : 2,  "op" : "u",  "ns" : "test.mycoll",  "o2" : {  "_id" : 0 },  "wt" : ISODate("2017-06-21T04:10:41.166Z"),  "o" : {  "$set" : {  "a.10" : 10,  "a.2" : 2 } } }
      

            Assignee:
            justin.seyster@mongodb.com Justin Seyster
            Reporter:
            max.hirschhorn@mongodb.com Max Hirschhorn
            Votes:
            0 Vote for this issue
            Watchers:
            9 Start watching this issue

              Created:
              Updated:
              Resolved: