Cihan Bebek
Cihan Bebek

Reputation: 418

MongoDB: How to add or update array object depending if its found or not?

What mongoDB operation can I use to add a object to array, or, if object is already in array then update one of its values.

Here is an example of my mongodb data:

    {
      "_id" : "1",
      "channelStatuses" : [
        {
          "channel" : "FOO",
          "status" : "done"
        }
      ]
    },
    {
      "_id" : "2",
      "channelStatuses" : [
        {
          "channel" : "BAR",
          "status" : "done"
        }
      ]
    },
    {
      "_id" : "3",
      "channelStatuses" : [
        {
          "channel" : "BAZ",
          "status" : "error"
        }
      ]
    },
    {
      "_id" : "3",
      "channelStatuses" : []
    }

What I would want to do, is to use mongodb-update to update all the data in the collection. Lets say I need to modify the statuses of all 'BAR'-channels. I want the update to either:

  1. Add a new channelStatus {"channel" : "BAR", "status" : "done"} to all objects in the collection.

  2. If a object already has a channelStatus with "channel" : "BAR", it would only update the "status" to "done" of that object.

If I simply use addToSet, it will add duplicates, for example: channelStatuses:[{"channel" : "BAR", "status" : "done"}, {"channel" : "BAR", "status" : "error"}]

An acceptable way for me to do this would be to first delete the old object, and then use addToSet to add the new one. But is there a way to do this in one update?

Upvotes: 0

Views: 81

Answers (1)

zangw
zangw

Reputation: 48566

If a object already has a channelStatus with "channel" : "BAR", update the value of status through $set

> db.collection.update({'channelStatuses.channel': {$eq: 'BAR'}}, 
                       {$set: {'channelStatuses.$.status': 'done'}}, {multi: true})

Otherwise, add new channel to channelStatuses through $addToSet

> db.collection.update({'channelStatuses.channel': {$ne: 'BAR'}}, 
                       {$addToSet: {'channelStatuses': {channel: 'BAR', status: 'done'}}}, 
                       {multi: true})

Upvotes: 1

Related Questions