Document not saving after finding and modifying in Mongoose - node.js

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);
}
})
});
}
});

Related

When you delete user let the user posts get deleted too in node js

Please am finding it difficult to delete user and also get the user posts removed automatically. I can only delete user or the user posts separately but I want it in a way that when I delete the user from the database the user posts also get deleted
You can look into mongoose pre middleware something like this should work:
UserSchema.pre('remove', function (next) {
let id = this._id
Post.deleteMany({ user: id }, function (err, result) {
if (err) {
next(err)
} else {
next()
}
})
})
The call the middleware like this :
User.findById(id, function (err, doc) {
if (err) {
console.log(err)
return res.status(500).send('Something went wrong')
} else {
if (!doc)
return res.status(404).send('User with the given id not found')
doc.remove(function (err, postData) {
if (err) {
throw err
} else {
return res.send('User successfully deleted')
}
})
}
})

why does my express route work for "/" but not "/:id"?

I was troubleshooting why my route wasn't working and i came across this.
In my ./routes/jobs.js,
router.delete("/:id", (req, res) => {
Job.findByIdAndDelete(req.params.id, (err, job) => {
if (!err) {
res.json({ msg: "job deleted"});
} else {
console.log(err);
}
});
});
When i tested on postman, Delete - http://localhost:5000/dashboard/60b9405e1ea
Would return the id only 60b9405e1ea and not delete the db job.
I changed my route to "/" and tested it out. using http://localhost:5000/dashboard in postman.
router.delete("/", (req, res) => {
Job.findByIdAndDelete(req.params.id, (err, job) => {
if (!err) {
res.json({ msg: "job deleted"});
} else {
console.log(err);
}
});
It executed the delete request with {msg: "job deleted"}. (Obviously didnt delete db job since no id was given).
Keep in mind in my server.js im using,
app.use("/dashboard", require("./routes/jobs"));
Any help would be appreciated on why /:id is not being executed
As you are getting the id in the console, it's the problem with the query you make.
Try any of these,
Model.remove({ _id: req.body.id }, function(err) {
if (!err) {
message.type = 'notification!';
}
else {
message.type = 'error';
}
});
or
Model.findOneAndRemove({id: req.params.id}, function(err){
});
or a traditional approach:
Model.findById(id, function (err, doc) {
if (err) {
// handle error
}
doc.remove(callback); //Removes the document
})

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');
}
);

NodeJS / Mongoose Filter JSON

I am building a JSON API with ExpressJS, NodeJS and Mongoose:
Input -> id:
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}, function (err, product) {
if (!err) {
console.log(product);
return res.send(product);
} else {
return console.log(err);
}
});
});
It shows well the JSON:
[{"_id":"B443U433","date":"2014-08-12","reference":"azerty","file":"087601.png","
....:.
{"_id":"HGF6789","date":"2013-09-11","reference":"azerty","file":"5678.pnf","
...
I just want to display the _id in the JSON, so it is good when I have lots of data.
How I can do that? Something like a filter?
You can chain calls to select and lean to retrieve just the fields you want from the docs you're querying:
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}).select('_id').lean().exec(
function (err, product) {
if (!err) {
console.log(product);
return res.send(product);
} else {
return console.log(err);
}
});
});
You would have to iterate over your "products" object to obtain the ids
Something like this:
(Disclaimer: I haven't tested this)
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}, function (err, product) {
if (!err) {
console.log(product);
var ids = new Array();
for(var i = 0; i < product.length; i++){
ids.push(product[i]._id);
}
return res.send(JSON.stringify(ids));
} else {
return console.log(err);
}
});
});
--Edit
Also, "products" may already be a JSON string. You may want to parse it before looping.
product = JSON.parse(product);
Other answers are true but I think it's better to limit data in mongoose like this :(it's same as mongo shell commands)
app.get('/folder/:id', function (req, res){
Cars.find({reference: req.params.id} ,{ _id : true } ,function (err, product) {
if (!err) {
console.log(product);
} else {
console.log(err);
}
});
});

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