1

I have the following schema:

var UserSchema = new Schema({
  username: { type: String, required: true },
  password: { type: String, required: true },
  userType: { type: String, default: 'user'},
  quizzHistory: [{
    quizzName: String,
    quizzScore: Number
  }]
});

my goal is to change document into embedded quizzHistory or insert new one if not exists document in embedded quizzeHistory

I try to set document into embedded quizzHistory :

User.findOneAndUpdate({ _id: req.session.user['_id'], 'quizzHistory.quizzName': testName},
{ 
    '$set': {
        'quizzHistory.$.quizzName': testName,
        'quizzHistory.$.quizzScore': finalScore
    }
}, {upsert: true},
function(err, upd) {
  console.log("added");
})

code above works if there is document in quizzHistory with required _id and quizzHistory.quizzName,but don't pushed new one if there isn't any document.

Is there any way in Mongodb to change document into embedded collection or insert new one if not exists ?

3 Answers 3

2

the reason is because you are using "find and update" you are not handling the condition when the row hasn't been found and create a new document, being said that you need manage the in a different way like

User.update({ _id: req.session.user['_id'], 'quizzHistory.quizzName': testName},
{ 
    '$push': {
        'quizzHistory.quizzName': testName,
        'quizzHistory.quizzScore': finalScore
    }
}, {upsert: true},
function(err, upd) {
  console.log("added");
})
Sign up to request clarification or add additional context in comments.

3 Comments

hi @jack.the.ripper thanks for your answer, there is no way to do it without condition?
which condition? can you elaborate a little bit more?
i will do user.find and if it returns empty array i use $push otherwise $set
1

this worked for me

User.update({ _id: req.session.user['_id'],'quizzHistory.quizzName':testName},
{ 
    $set: {
        "quizzHistory.$.quizzName":testName,
        "quizzHistory.$.quizzScore":finalScore
    }
},
function(err, upd) {
  if(!upd){
        User.update({ _id: req.session.user['_id']},
        { "$addToSet": { quizzHistory:  newScoreData }},function(err,data){
        });
  }
});

Comments

1

If you want to benefit for all possible plugins and methods added to model and don't want to fight with actual Mongo queries you should first retrieve user object, then push new element to quizzHistory array and do save. Something like below (you need to align that code to your needs).

var entry = {
  quizzName : 'abc',
  quizzScore : 123
};

User.findOne({_id:id, function(err, object) {
  if(err) {
    return someErrorCallback();
  }
  var 
  object.quizzHistory.push(entry);
  object.save(function(err) {
    if(err) {
      return someErrorCallback();
    }
    someSuccessCallback();
  });
});

Updating directly may be efficient, but questions usage of mongoose.

Hope it makes sense.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.