title: Update nested object in MongoDB if it exists, otherwise add it
body: <p>I've got a json doc like this in mongoDB:</p>
  
  <pre><code> { "_id" : ObjectId("57ed88c0965bedd2b11d5727"),
     "refid" : 2,
     "votes" : [
       { "ip" : "127.0.2.1", "rating" : 5 },
       { "ip" : "127.0.3.1", "rating" : 2 },
       { "ip" : "127.59.83.210", "rating" : 50 },
       { "ip" : "127.56.26.191", "rating" : 5 },
       { "ip" : "127.59.83.210", "rating" : 5 },
       { "ip" : "127.59.83.210", "rating" : 30 }
      ]
   }
  </code></pre>
  
  <p>And instead of creating dupes per IP, I want to update the record found if the IP exists, or add a new entry if it doesn't. There are tons of questions on how to do similar operations, but none that I could find exactly asking something this simple. I am trying this in Node.js:</p>
  
  <pre><code>db.collection('ratings').update( { "refid":refid, "votes.ip":ip },
    {
      $push: { votes: { "ip":ip, "rating":rating }
    }
  })
  </code></pre>
  
  <p>But it just keeps adding new entries when I vote from the same IP.</p>
  
  <p><strong>NOTE:</strong> I am not using Mongoose.</p>
  
  <p>I apologize if my question is overly elementary, I'm pretty new to MongoDB. I'm just wondering if there's a good way to do this baked in rather than iterating through every record in "votes" programmatically. Thanks!</p>
  
  <p><strong>EDIT:</strong> What I'm asking isn't currently possible, I've marked an answer below correct which contains the explanation and a link to a ticket at MongoDB for an enhancement.</p>
  
  <p>As for the scenario in my question here, the code below works for me. I have no idea how good or bad it is performance wise, but it covers all of these scenarios:</p>
  
  <ul>
  <li>If the record doesn't exist at all, create it</li>
  <li>If the record exists, look for the IP and if found, update the rating</li>
  <li>If the record exists but the IP does not, insert a new rating</li>
  </ul>
  
  <p>Works:</p>
  
  <pre><code>db.collection('ratings').findOne({ "refid":refid }).then(function(vote) {  
    if (vote == null) {
      newrating = {refid: refid, votes: [{ ip: ip, rating: rating }]};
      db.collection('ratings').save(newrating);
    } else {
      db.collection('ratings').findOne({ "refid":refid, "votes.ip":ip }).then(function(rate) {
        if (rate != null) {
          db.collection('ratings').update(
            { refid: refid, "votes.ip" : ip },
            { $set: { "votes.$.rating" : rating } }
          )
        } else {
          db.collection('ratings').update({"refid":refid,"votes.ip" : {$ne : ip }},
            { $push: { votes: { "ip" : ip, "rating" : rating, }}}
          )
        }
      })
    }
  })
  </code></pre>