How to update the document if it exist else save it? - node.js

I am trying to update the document if it exist else save it. I am using below code from this SO question
user.update({User_id:req.body.User_id}, {$setOnInsert: req.body},
{upsert: true}, function (err, data) {
if(err) {
res.json(err);
} else {
res.json('Successfully inserted ');
}
});
but it is throwing the below error
TypeError: oldCb is not a function

Related

How to find a record and insert the same record in Mongoose?

Here I want to get a record and I need to insert the same record with slight modification. But I can't see the data in my new record which I found in my get record. Here is what I tried, can anyone help me? I think the problem is with this line var institution = new Institution(data);:
Institution.find({_id:i._id}).exec(function (err, result) {
if(result)
transferData(result);
}
});
});
}
function transferData(data){
var institution = new Institution(data);
institution.name = 'xxxx';
institution.save(function (err, data) {
if (err) {
return res.status(400).send({ message: errorHandler.getErrorMessage(err) });
} else {
console.log('Data Inserted Successfully');
}
});
}
find() returns an array of docs that match the criteria in the callback hence the line
var institution = new Institution(data);
will not work as it's expecting a Document not an array.
You could use findById() method as:
Institution.findById(i._id).exec(function (err, result) {
if (result) transferData(result);
});
function transferData(data) {
var institution = new Institution(data);
institution.name = 'xxxx';
institution.save(function (err, data) {
if (err) {
return res.status(400).send({ message: errorHandler.getErrorMessage(err) });
} else {
console.log('Data Inserted Successfully');
}
});
}
A much better approach would involve the findByIdAndUpdate() method:
Institution.findByIdAndUpdate(i._id, {name: 'xxxx'}, {upsert: true}, function (err, data) {
if (err) {
return res.status(400).send({ message: errorHandler.getErrorMessage(err) });
} else {
console.log('Data Inserted Successfully');
}
);

Document not saving after finding and modifying in Mongoose

I have a route to remove a team and all requests to join that specific team, which is nested in a JoinTeamRequests array in the UserProfiles. The idea is to remove all traces of invites to that team once it has been deleted. I am using the MEAN stack. I am still new at this so any other advice or suggestions would be great.
here is my route:
//Remove a specific team
.delete (function (req, res) {
//Delete the team - works
TeamProfile.remove({
_id : req.body.TeamID
}, function (err, draft) {
if (err)
res.send(err);
});
UserProfile.find(
function (err, allProfiles) {
for (var i in allProfiles) {
for (var x in allProfiles[i].JoinTeamRequests) {
if (allProfiles[i].JoinTeamRequests[x].TeamID == req.body.TeamID) {
allProfiles[i].JoinTeamRequests.splice(x, 1);
console.log(allProfiles[i]); //logs the correct profile and is modified
}
}
}
}).exec(function (err, allProfiles) {
allProfiles.save(function (err) { //error thrown here
if (err)
res.send(err);
res.json({
message : 'Team Successfully deleted'
});
});
});
});
However, I get an error: TypeError: allProfiles.save is not a function.
Why is it throwing this error?
First of all it is more common to perform search in next form:
UserProfile.find({'JoinTeamRequests.TeamID': req.body.TeamID})
Secondly, after execution you have to check if returned array is not empty:
if(allProfiles && allProfiles.length) {
}
I think it could be possible to execute this in one statement, but for now, try the next chunk of code:
UserProfile.find({'JoinTeamRequests.TeamID': req.body.TeamID}).exec(function (err, users) {
if(err) {
return res.end(err);
}
if(users && users.length) {
users.forEach(function(user) {
user.JoinTeamRequests.remove(req.body.TeamID);
user.save(function(err) {
if(err) {
return res.end(err);
}
})
});
}
});

Mongoose model.save( ) is not working as expected

I have this code and MongoDB is passing back an error after I attempt to save a new document:
var data = {
_id: '55d65cfde9cf73322361860b' // _id is a string here
};
var model = new Model(data);
model.save(function (err, result) {
if (err) {
done(err); //the error is captured here in my code
}
else{
done(null, result);
}
});
and I get an error:
MongoError: E11000 duplicate key error index: dev_local_db_smartconnect.jobs.$_id_ dup key: { : ObjectId('55d65cfde9cf73322361860b') }
however, I was under the impression that save would update the model/document if it exists (by using an implicit upsert=true option), and it would use the _id field to look for an existing document.
Does anyone know why this error would occur?
On the other hand, this works for me:
where data is the new data for the model, and _id is a string not an ObjectID, and Model is the mongoose class, not the instance.
Model.update({_id:_id}, {$set: data}, {upsert:true} , function(err,result){
if (err) {
done(err);
}
else if (result) {
done(null, result);
}
else {
done(new Error('grave error'));
}
});
Since you are creating a new local document Mongoose doesn't know it already exists on the server so it will try to save it as a new document. Mongo will then reject the document since an existing document with that ID already exists.
If you query for that document first and then save the returned document it would work as expected. Something like this:
Model.find({id: '55d65cfde9cf73322361860b'}, function (err, doc) {
// update doc with something
// ...
doc.save(function (err, result) {
if (err) {
done(err); //the error is captured here in my code
}
else {
done(null, result);
}
});
});

Mongoose change document _id on save/update

a quick one:
Why is Mongoose change/upgrading the _id field of a document when I push an update?
Is this an intended behavior?
Thanks.
This is the update I use inside my PUT route, and it returns successfully the updated model, but unfortunately with a new _id for doc
Document.findById(req.params.doc_id, function (err, doc) {
if (err)
res.send(err)
// Do some subdoc stuff here …
doc.save(function (err) {
if (!err) {
console.log('Success!');
res.json(doc);
} else {
console.log(err);
}
});
});
Okay, problem solved:
I was logging the wrong _id (doh!)
Mongoose docs http://mongoosejs.com/docs/2.7.x/docs/model-definition.html
suggest using update or findOne
ex:
var query = { name: 'borne' };
Document.update({"_id": req.params.doc_id}, { name: 'jason borne' }, {}, function(err, numAffected){
if (!err) {
console.log('Success!');
res.json(numAffected);
} else {
console.log(err);
}
});
or
Model.findOne({ "_id": req.params.doc_id }, function (err, doc){
doc.name = 'jason borne';
doc.save();
// here you could use your save instead, but try not to use the doc again
// it is confusing
// doc.save(function (err, documentSaved, numberAffected) {
// if (!err) {
// console.log('Success!');
// res.json(documentSaved);
// } else {
// console.log(err);
// }
// });
});
Later I also found the findById update suggested in some docs http://mongoosejs.com/docs/documents.html, which seems to be up to date, check the version you are using and also double check the two times you are using doc in your functions here. Also you can check your mongoDB and see if there are more than one record getting saved.
db.documents.find( {} )

apply update options without save for pre-validation - mongoosejs

In any webapp i press a plus button and a value will be increased.
When i hit the button fast the validation does not work, cause the validations does not prevent (excepted behavior, the value is not out of the validations range). But the value will be setted down further, cause the rest of the reqeust will be submitted.
Important: the update options are dynamically (for instance $inc or $set).
Current Code
module.model.update({ _id: id }, options /* are dynamic */, { safe: true }, function (err, updatedDocument) {
if (err) return respond(400, err);
module.model.findOne({ _id: id }, function (err, foundDocument) {
if (err) return respond(400, err);
foundDocument.validate(function (err) {
if (err) return respond(400, err);
return respond(200, foundDocument); // callback method
});
});
});
First guess to prevent the problem
module.model.findOne({ _id: id }, function (err, foundDocument) {
foundDocument.set(options);
foundDocument.validate(function (err) {
if (err) return respond(400, err);
foundDocument.save(function (err, savedDocument) {
if (err) return respond(400, err);
return respond(200, doc);
});
});
});
...then the save just will preformed when the validation is valid.
But there is a porblem: The set method does not support $inc or other pseudo setters, or does it?
I saw the possibility to use the constructor of the update function (Show Code), but i don't know how to use it: this.constructor.update.apply(this.constructor, args);
Do you have any good practise for this problem ?
The solution was to create a customized version for $inc.
What i've done is to replace the set method of mongoosejs.
This is now extendable, but a quiet custom way to validate before an update. When someone have another solution. Post it please.
module.model.findOne({ _id: id }, function (err, foundDocument) {
for(var optionsProp in options) {
if(optionsProp === '$inc') {
for(var incProp in options[optionsProp]) {
foundDocument[incProp] += options[optionsProp][incProp];
}
}
}
foundDocument.validate(function (err) {
if (err) return respond(400, err);
foundDocument.save(function (err, savedDocument) {
if (err) return respond(400, err);
return respond(200, savedDocument);
});
});
});

Resources