Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB - Upsert with increment

I am trying to run the following query:

data = {
    'user_id':1,
    'text':'Lorem ipsum',
    '$inc':{'count':1}, 
    '$set':{'updated':datetime.now()},
}
self.db.collection('collection').update({'user_id':1}, data, upsert=True)

but the two '$' queries cause it to fail. Is it possible to do this within one statement?

like image 863
Hanpan Avatar asked Oct 23 '11 20:10

Hanpan


2 Answers

First of all, when you ask a question like this it's very helpful to add information on why it's failing (e.g. copy the error).

Your query fails because you're mixing $ operators with document overrides. You should use the $set operator for the user_id and text fields as well (although the user_id part in your update is irrelevant at this example).

So convert this to pymongo query:

db.test.update({user_id:1}, 
    {$set:{text:"Lorem ipsum", updated:new Date()}, $inc:{count:1}}, 
    true, 
    false)

I've removed the user_id in the update because that isn't necessary. If the document exists this value will already be 1. If it doesn't exist the upsert will copy the query part of your update into the new document.

like image 199
Remon van Vliet Avatar answered Nov 17 '22 18:11

Remon van Vliet


If you're trying to do the following: If the doc doesn't exist, insert a new doc. If it exists, then only increment one field. Then you can use a combo of $setOnInsert and $inc. If the song exists then $setOnInsert won't do anything and $inc will increase the value of "listened". If the song doesn't exist, then it will create a new doc with the fields "songId" and "songName". Then $inc will create the field and set the value to be 1.

let songsSchema = new mongoose.Schema({
      songId: String,
      songName: String,
      listened: Number
    })
    
let Song = mongoose.model('Song', songsSchema);
let saveSong = (song) => {
  return Song.updateOne(
    {songId: song.songId},
    {
      $inc: {listened: 1},
      $setOnInsert: {
        songId: song.songId,
        songName: song.songName,
      }
    },
    {upsert: true}
  )
  .then((savedSong) => {
    return savedSong;
  })
  .catch((err) => {
    console.log('ERROR SAVING SONG IN DB', err);
  })
       
like image 37
Farhan Ali Avatar answered Nov 17 '22 19:11

Farhan Ali