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

$ Positional Array Update Operator does not work as expected

    • Type: Icon: Bug Bug
    • Resolution: Works as Designed
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 3.6.6
    • Component/s: Querying
    • Labels:
      None
    • ALL
    • Hide

      Insert this test document:

       

      db.test.insert({
      	"_id" : NumberLong("1046644416921"),
      	"teachers" : [
      		{ "lid" : 203745 },
      		{ "lid" : 5551146 }
      	],	
      	"asn" : [
      		{ "_id" : ObjectId("5b5a4a2cf3c2c0aad9e6237b") },
      		{ "_id" : ObjectId("5b5a4abdf3c2c0aad9e62382") },
      		{ "_id" : ObjectId("5b5a4c30f3c2c0aad9e62389") }
      	]
      })
      

       

      Issue the following update:

       

      db.test.update({ "asn._id" : new ObjectId("5b5a4a2cf3c2c0aad9e6237b"), "teachers.lid" : 5551146 , "_id" : 1046644416921 },
      { "$inc" : { "asn.$.mods" : 1 } })
      

      Expected output of db.test.findOne()

       

       

      {
      	"_id" : NumberLong("1046644416921"),
      	"teachers" : [
      		{
      			"lid" : 203745
      		},
      		{
      			"lid" : 5551146
      		}
      	],
      	"asn" : [
      		{
      			"_id" : ObjectId("5b5a4a2cf3c2c0aad9e6237b")
      			"mods" : 1
      		},
      		{
      			"_id" : ObjectId("5b5a4abdf3c2c0aad9e62382"),
      		},
      		{
      			"_id" : ObjectId("5b5a4c30f3c2c0aad9e62389")
      		}
      	]
      }
      

       

       

      Actual output:

      {
      	"_id" : NumberLong("1046644416921"),
      	"teachers" : [
      		{
      			"lid" : 203745
      		},
      		{
      			"lid" : 5551146
      		}
      	],
      	"asn" : [
      		{
      			"_id" : ObjectId("5b5a4a2cf3c2c0aad9e6237b")
      		},
      		{
      			"_id" : ObjectId("5b5a4abdf3c2c0aad9e62382"),
      			"mods" : 1
      		},
      		{
      			"_id" : ObjectId("5b5a4c30f3c2c0aad9e62389")
      		}
      	]
      }
      

      Notice the wrong sub-document was updated!

      Also, please note that if we do this query, we have the same problem.

      db.test.update({ "asn" : {$elemMatch:{ _id:new ObjectId("5b5a4a2cf3c2c0aad9e6237b")}}, 
                  "teachers.lid" : 5551146 , 
                   "_id" : 1046644416921 },
      { "$inc" : { "asn.$.mods" : 1 } })
      

       

      However, if you remove the "teachers.lid" from the query, it behaves as expected.  Also, if you do it with the "new-style" array filters, it works perfectly:

      db.test.update({ "asn" : { $elemMatch:{_id:new ObjectId("5b5a4a2cf3c2c0aad9e6237b")}},
      	"teachers.lid" : 5551146,
      	"_id" : 1046644416921 }, 
      	{ "$inc" : { "asn.$[element].mods" : 1 } },
      { arrayFilters:[{ 'element._id': new ObjectId("5b5a4a2cf3c2c0aad9e6237b")  }]})
      

       

       

      Show
      Insert this test document:   db.test.insert({ "_id" : NumberLong( "1046644416921" ), "teachers" : [ { "lid" : 203745 }, { "lid" : 5551146 } ], "asn" : [ { "_id" : ObjectId( "5b5a4a2cf3c2c0aad9e6237b" ) }, { "_id" : ObjectId( "5b5a4abdf3c2c0aad9e62382" ) }, { "_id" : ObjectId( "5b5a4c30f3c2c0aad9e62389" ) } ] })   Issue the following update:   db.test.update({ "asn._id" : new ObjectId( "5b5a4a2cf3c2c0aad9e6237b" ), "teachers.lid" : 5551146 , "_id" : 1046644416921 }, { "$inc" : { "asn.$.mods" : 1 } }) Expected output of db.test.findOne()     { "_id" : NumberLong( "1046644416921" ), "teachers" : [ { "lid" : 203745 }, { "lid" : 5551146 } ], "asn" : [ { "_id" : ObjectId( "5b5a4a2cf3c2c0aad9e6237b" ) "mods" : 1 }, { "_id" : ObjectId( "5b5a4abdf3c2c0aad9e62382" ), }, { "_id" : ObjectId( "5b5a4c30f3c2c0aad9e62389" ) } ] }     Actual output: { "_id" : NumberLong( "1046644416921" ), "teachers" : [ { "lid" : 203745 }, { "lid" : 5551146 } ], "asn" : [ { "_id" : ObjectId( "5b5a4a2cf3c2c0aad9e6237b" ) }, { "_id" : ObjectId( "5b5a4abdf3c2c0aad9e62382" ), "mods" : 1 }, { "_id" : ObjectId( "5b5a4c30f3c2c0aad9e62389" ) } ] } Notice the wrong sub-document was updated! Also, please note that if we do this query, we have the same problem. db.test.update({ "asn" : {$elemMatch:{ _id: new ObjectId( "5b5a4a2cf3c2c0aad9e6237b" )}}, "teachers.lid" : 5551146 , "_id" : 1046644416921 }, { "$inc" : { "asn.$.mods" : 1 } })   However, if you remove the "teachers.lid" from the query, it behaves as expected.  Also, if you do it with the "new-style" array filters, it works perfectly: db.test.update({ "asn" : { $elemMatch:{_id: new ObjectId( "5b5a4a2cf3c2c0aad9e6237b" )}}, "teachers.lid" : 5551146, "_id" : 1046644416921 }, { "$inc" : { "asn.$[element].mods" : 1 } }, { arrayFilters:[{ 'element._id' : new ObjectId( "5b5a4a2cf3c2c0aad9e6237b" )  }]})    

      If you include multiple array fields in a query, then the "$" positional array operator does not work, or worse, update the wrong (non-matching) sub-document.  

            Assignee:
            nick.brewer Nick Brewer
            Reporter:
            tinkler@vocabulary.com Marc Tinkler
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: