0

I have a function that is supposed to find a question by "ID" from the mongo database and return it, if it doesn't find one it creates one and then returns it. it is the only function in my code that is able to create new question entities in the database. here it is: (btw i am using the official MongoDb driver for nodeJs)

function getQuestionEntity(questionID, cb){
    const questions = db.collection('questions')

    questions.findOneAndUpdate(
        {ID: questionID},
        {$setOnInsert: 
            {
                ID: questionID,
                rating: 1.5,
                options: 4,
                answeredRight: 0,
                answeredWrong: 0

            }
        },
        {
            returnOriginal: false,
            upsert: true
        },
        (err, r)=>{
            if(err){throw new Error(err)}
            cb(r.value)
        }
    )
}

I have read that findOneAndUpdate is an atomic operation, which means that even if i loop this function asynchronously to the end of times, still i will not get two question entities with the same "ID" field in the database, yet that is exactly what happens.

Is there anything wrong with my code? am i wrong about my assumptions?

Carpet4
  • 578
  • 1
  • 8
  • 17
  • 1
    An update operation is atomic, but an upsert isn't. See [here](https://stackoverflow.com/questions/37295648/mongoose-duplicate-key-error-with-upsert/37485551#37485551). So you need to add a unique index to `ID` and then handle the duplicate key error when it occurs. – JohnnyHK Apr 10 '17 at 21:19

1 Answers1

0

Do not set the id of the document twice, then you would end with something like this:

 questions.findOneAndUpdate(
   {ID: questionID},
   {$set: {rating: 1.5, options: 4, answeredRight: 0, answeredWrong: 0}}, 
   {upsert: true},
    (err, r)=>{
        if(err){throw new Error(err)}
        cb(r.value)
    }
   )

I have not tested this code in nodejs; Do not use $setOnInsert as it only works when it is an insert and it will not update the keys when the document already exists.

Euclides
  • 405
  • 7
  • 11
  • the id i insert is one i get from a different database, also i do want to not update if it already exists. – Carpet4 Apr 12 '17 at 05:18