why does my express route work for "/" but not "/:id"? - node.js

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

Related

How do I get the ID of the document I just inserted into MongoDB? (API)

I am trying to get the ID of the document that I just inserted into mongoDB. Here is the node.js code:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err) => {
if (err) {
res.status(500).send(err);
} else {
var id = dbGroup._id;
res.status(201).send(id);
}
});
});
I have tried various things, like adding a group to the function:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err, group) => {
if (err) {
res.status(500).send(err);
} else {
var id = group._id;
res.status(201).send(id);
}
});
});
But that also does not work, so I tested if my even get the API response on the front end with:
res.status(201).send("test");
Which works perfectly fine. So I don't know why this doesn't work, because all the documentation says this is the way.
I figured a way to get the id. It may be not the most efficient way, because it sends all the data it gets but it gets the job done.
Backend:
app.post("/groups/new", (req, res) => {
const dbGroup = req.body;
Groups.create(dbGroup, (err, data) => {
if (err) {
res.status(500).send(err);
} else {
res.status(201).send(data);
}
});
});
Front end:
axios.post("/groups/new", {
groupname: roomName,
}).then((res) => {
roomid = res.data._id;
});

Sending a POST request in Postman set to send a certain status sends the default status

I want that my POST request sends a HTTP 409 in a certain case, so this is the code:
res.status(409).send();
However, when I tun the request in Postman it shows the result 200 OK. I put some logs in the code and I'm sure that the above line is hit.
What is wrong?
UPDATE:
Here is the full method:
app.post('/orders/:order_id/sync_status', (req, res) => {
order.findOne({ order_id: req.params.order_id},
function(err, results) {
if (err) {
res.send(`error: ${error}`);
} else if (!results) {
res.send(`no order with order_id: ${req.params.order_id}`);
} else {
status.findOne({ order_id: req.params.order_id},
function(err, result) {
if (err) {
res.send(`error: ${error}`);
} else if (result) {
res.status(409).send();
} else {
const newStatus = new status (req.body);
newStatus.save();
}
});
}
res.end();
});
});
and the Postman request:
The simple reason is because you have res.end()
The longer answer is because res.end() is executed before this piece
status.findOne({order_id: req.params.order_id}, function(err, result) {
if (err) {
res.send(`error: ${error}`);
} else if (result) {
res.status(409).send();
} else {
const newStatus = new status(req.body);
newStatus.save();
}
});
got executed due to asynchronous call/callback.
Without testing, your final code should look like this
app.post('/orders/:order_id/sync_status', (req, res) => {
order.findOne({order_id: req.params.order_id}, function(err, results) {
if (err) {
return res.send(`error: ${error}`);
}
if (!results) {
return res.send(`no order with order_id: ${req.params.order_id}`);
}
status.findOne({order_id: req.params.order_id}, function(err, result) {
if (err) {
return res.send(`error: ${error}`);
}
if (result) {
return res.status(409).send();
}
const newStatus = new status(req.body);
newStatus.save();
return res.end();
});
});
});

node.js api keep code dry

I was wondering , what is the best practice to keep the code DRY when developing node.js api with database calls.
I seems like I'm having alot of repeated code.
For example, look at this:
app.get('/api/users_count', function (req,res) {
pool.connect(function(err, client, done) {
if(err) {
return console.error('error fetching client from pool', err);
}
client.query('SELECT count(*) FROM users;', function(err, result) {
done();
if(err) {
return console.error('error running query', err);
}
res.json({"users count": result.rows[0].count});
});
});
});
and this:
app.get('/api/users/:id', function (req,res) {
pool.connect(function(err, client, done) {
if(err) {
return console.error('error fetching client from pool', err);
}
client.query('SELECT name FROM users WHERE id=$1;',req.param.id, function(err, result) {
done();
if(err) {
return console.error('error running query', err);
}
res.json({"user name": result.rows[0].name});
});
});
});
How can I avoid the repeating of error handing , connect call, and just focus on route and query.
Thanks!
Take a look at sample below, should help
//Create fn that connects, pulls data, and passes it to callback
function customPool(query, values, callback) {
pool.connect(function(err, client, done) {
if(err)
return callback(err);
client.query(query, values, function(q_err, result) {
done();
if(q_err)
return callback(q_err);
callback(null, result.rows);
});
}
}
//Reuse it
app.get('/api/users_count', function (req,res) {
var query = 'SELECT count(*) FROM users;';
customPool(query, undefined, function(err, rows) {
if(err)
return console.error('error fetching client from pool', err);
res.json({"users count": rows[0].count});
});
});
app.get('/api/users/:id', function (req,res) {
var query = 'SELECT name FROM users WHERE id=$1;';
customPool(query, req.params.id, function(err, rows) { //<-- notice, req.params.id not req.param.id
if(err)
return console.error('error fetching client from pool', err);
res.json({"users name": rows[0].name});
});
});
For starters, use pg-promise for database communications, to avoid connecting manually. Then your code will be way simpler, as shown below.
code 1:
app.get('/api/users_count', function (req, res) {
db.one('SELECT count(*) FROM users')
.then(data=> {
res.json({"users count": +data.count});
})
.catch(error=> {
// should provide a response here also ;)
console.error(error);
});
});
code 2:
app.get('/api/users/:id', function (req, res) {
db.one('SELECT name FROM users WHERE id=$1', +req.param.id)
.then(user=> {
res.json({"user name": user.name});
})
.catch(error=> {
// should provide a response here also ;)
console.error(error);
});
});
Then you can simplify it further, by implementing a generic request->response logic, depending on your application's requirements.

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

Why my nodejs requests are slow?

Im new in nodejs, and Im trying to learn by creating an app that has a list of users, that I can add and remove those users. Im using angularjs in frontend to send request to nodejs and after that to mongodb. The problem is that, if I click a lot of times in the button "adduser" a lot of times, my app goes slow.
To interact to mongodb I use:
app.get('/users',function (req, res) {
mongoose.model('Usuario').find(function (err, list) {
res.send(list);
});
});
app.post('/addusuario', function (req,res) {
var usuario = new Usuario(req.body);
usuario.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('Usuario salvo com sucesso');
}
}); });
app.delete('/delusuario/:id', function (req, res) {
var id = req.params.id;
mongoose.model('Usuario').findByIdAndRemove(id , function(err) {
if(err) {
console.log(err);
} else {
console.log('Usuario removido com sucesso!');
}
});
});
Im my angularapp:
app.controller('AppCtrl', function($scope, $http, Data) {
function reload() {
Data.get('users').then(function(data){
$scope.usuarios = data;
console.log(data);
});
};
$scope.addUsuario = function(usuario) {
Data.post('/addusuario', usuario);
reload();
};
$scope.deletarUsuario = function(id) {
Data.delete("/delusuario/"+id).then(function(result) {
});
reload();
};
reload();
});
I dont know why it is becaming slow after I click to add user more than 3 times..
What I see in your code that you are not sending an response back to the user, you should do something after insert or delete in the database. res.end();
You should rewrite your code in the following way:
app.get('/users',function (req, res) {
mongoose.model('Usuario').find(function (err, list) {
res.send(list);
});
});
app.post('/addusuario', function (req,res) {
var usuario = new Usuario(req.body);
usuario.save(function (err) {
if (err) {
console.log(err);
res.json({err: err});
} else {
res.json({ok: true});
console.log('Usuario salvo com sucesso');
}
}); });
app.delete('/delusuario/:id', function (req, res) {
var id = req.params.id;
mongoose.model('Usuario').findByIdAndRemove(id , function(err) {
if(err) {
console.log(err);
res.json({err: err});
} else {
res.json({ok: true});
console.log('Usuario removido com sucesso!');
}
});
});
You block the stack by not returning the response to the client. And this is most probably the cause of your slow request.

Resources