Search code examples
mongodbmongodb-update

Why is my MongoDb query inserting an embedded document on Update?


This is my MongoDB query:

db.events.update({date:{$gte: ISODate("2014-09-01T00:00:00Z")}},{$set:{"artists.$.soundcloud_toggle":false}},{multi:true,upsert:false})

Apparently I cannot use "artists.$.soundcloud_toggle" to update all artist documents within the artists array:

"The $ operator can update the first array element that matches multiple query criteria specified with the $elemMatch() operator. http://docs.mongodb.org/manual/reference/operator/update/positional/"

I'm happy to run the query a number of times changing the index of the array in order to set the soundcloud_toggle property of every artist in every event that matches the query e.g

artists.0.soundcloud_toggle
artists.1.soundcloud_toggle
artists.2.soundcloud_toggle
artists.3.soundcloud_toggle

The problem is: when there is say, only one artist document in the artists array and I run the query with "artists.1.soundcloud_toggle" It will insert an artist document into the artist array with a single property:

{
   "soundcloud_toggle" : true
},

(I have declared "upsert:false", which should be false by default anyways)

How do I stop the query from inserting a document and setting soundcloud_toggle:false when there is no existing document there? I only want it to update the property if an artist exists at the given artists array index.


Solution

  • If, like you said, you don't mind completing the operation with multiple queries, you can add an $exists condition to your filter.

    E.g. in the 5th iteration, when updating index=4, add: "artists.4": {$exists: true}, like:

    db.events.update(
        { date: {$gte: ISODate("2014-09-01T00:00:00Z")},
          "artists.4": {$exists: true} },
        { $set:{ "artists.4.soundcloud_toggle" :false } },
        { multi: true, upsert: false }
    )