Currently I am working on a nodeJS API, I have a model, and that model can have Media items, as you can see in my code here:
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
console.log(media);
}
});
model.total_media = 15;
responders.sendJsonOrError(err, res, model, next);
});
});
Problem is, that the code:
model.total_media = 15;
Is not showing up in the responder, which is strange, because if I clean the object with: model = []; it returns empty.
Once I add lean() to my query, it returns the total_media in the responder, but then I get the problem that when I do like this:
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
model.total_media = media;
}
});
responders.sendJsonOrError(err, res, model, next);
});
});
It is not populating the total_media, is there any other way to do this correctly?
Try with this. The response is sending before you assign values.
router.get('/:id', function(req, res, next) {
qbuilder.byId(Model,req)
.lean().exec(
function(err,model){
Media.count({'model.entity': model._id}, function(err, media){
if(media){
model.total_media = media;
}
responders.sendJsonOrError(err, res, model, next);
});
});
});
Related
I have built an API to GET and POST values into a database(MongoDB) using NodeJS and Express.
I am able to get only a single comment by the userid
(localhost:3000/comments/userid/3)
But I want to get all comments by a single user
/* GET /comments/userid/userid */
router.get('/userid/:userid', function(req, res, next) {
Comments.findOne({userId:req.params.userid}, function (err, post) {
if (err) return next(err);
res.json(post);
})
});
Is there any method to do this? Like the findOne method?
just do find with the query
router.get('/userid/:userid', function(req, res, next) {
Comments.find({userId:req.params.userid}, function (err, post) {
if (err) return next(err);
res.json(post);
})
});
route.js
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err) {
req.session.resultArray=resultArray;
}
});
console.log(req.session.resultArray);
res.render('restful',{resultArray:req.session.resultArray});
});
I don't know why I am getting as undefined when I am doing it console.log() in the above position.If I do console.log() just after the req.session.resultArray=resultArray then we are getting the result array.
I want to display this resultArray in my view.ejs. Can anyone suggest me how to solve it.What is the thing I am missing it out?
The console.log runs before the async function actually gets the details from the database. so you get undefined.
Do the render inside the callback. i.e, after you assign result array to session.
router.get('/restful', (req, res, next) {
User.show_deatils(req, res, function(err, resultArray) {
if(!err) {
req.session.resultArray=resultArray;
return res.render('restful' {resultArray:req.session.resultArray}));
}
});
});
Just do like this
router.get('/restful', function(req, res){
console.log("before");
User.show_deatils(req, res, function(err, resultArray){
if(!err) {
res.render('restful',{resultArray:resultArray});
}
});
});
I think this is what you want.
Here is the code:
exports.delete = function (req, res, next) {
console.log(req.user);
req.user.remove(function (err) {
if(err) {
return next(err);
} else {
res.json(req.user);
}
})
};
Of course this function is callback of delete method, what I don't understand is that, why removing req.user also deletes the specific user from MongoDB, as it is just a request.
Edit:
I have another callback(GET) which is executed on the same route:
exports.userByID = function (req, res, next, id) {
User.findOne({
_id: id
}, function (err, user) {
if (err) {
return next(err);
} else {
req.user = user;
next();
}
});
};
User is MongoDB model.
Where you do your req.user = user you're setting the value of req.user to the instance of your mongodb model.
So, calling req.user.remove is in fact calling your mongodb model remove function.
Change your delete function to:
exports.delete = function (req, res, next) {
console.log(req.user);
delete req.user
//etc...
};
delete req.user will remove the user object from your request object
I'm learning express and am currently writing an API, and have this structure:
app.route('/api/brief/:_id')
.get(function(req, res, next) {
// Check if the _id is a valid ObjectId
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
// Do something
}else{
// Error
}
})
.put(function(req, res, next) {
// Check if the _id is a valid ObjectId
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
// Do something
}else{
// Error
}
})
.delete(function(req, res, next) {
// Check if the _id is a valid ObjectId
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
// Do something
}else{
// Error
}
});
Ideally I'd like to avoid the repetition (checking the validity of the ID).
Is there a way that I can structure the route as to avoid that repetition?
There are a few ways you can approach it. There is the app.all() method:
app.all("/api/*", function(req, res, next) {
if (req.params._id) {
if (mongoose.Types.ObjectId.isValid(req.params._id)) {
return next();
}
else {
// error handle
}
}
next();
});
Personally, I don't like catch-alls. I'd rather be more explicit:
function validateMongooseId (req, res, next) {
if ( mongoose.Types.ObjectId.isValid(req.params._id) ) {
return next();
}
else {
// error handle
}
}
function handleGet(req, res, next) {}
function handlePost(req, res, next) {}
function handlePut(req, res, next) {}
app.post("/api/brief", handlePost);
app.get("/api/brief/:_id", validateMongooseId, handleGet);
app.put("/api/brief/:_id", validateMongooseId, handlePut);
I put the .post() in there to demonstrate why I don't like the catch-all. It clearly doesn't apply to that endpoint. You may have other middleware functions that apply to it, so I'd rather explicitly have them on the endpoints that use them.
Hello guys here is my code:
function get_group(req, res, next) {
var send_result = function(err, group_list) {
[...]
res.send(group_list);
return next();
};
Group.findOne({'_id': req.params._id}, send_result);
}
Now how can I implement the async library (caolan) using async.series and combine the findOne() with send_result, the code as it is look pretty disorganised to me.
EDIT1:
I used this strategy but I am not sure is correct, any suggestion?
function get_group(req, res, next) {
async.waterfall([
function(callback) {
Group.findOne({'_id': req.params._id}, callback);
}
],
function (err, group_list){
res.send(group_list);
return next();
});
}
Any suggestion?
For what they call routes in Express.js you actually almost never need to use the async library. The reason is that routes are actually a sort of control flow them self. They take as many middleware as you want so you can divide your routes into small blocks of code.
For example lets say you want to get one record/document from a database do something with it and then send it as json. Then you can do the following:
var getOne = function(req, res, next){
db.one( 'some id', function(err, data){
if (err){
return next( { type: 'database', error: err } );
};
res.local( 'product', data );
next();
});
};
var transformProduct = function(req, res, next){
var product = res.locals().product;
transform( product, function(data){
res.local('product', data);
next();
});
};
var sendProduct = function(req, res, next){
var product = res.locals().product;
res.json(product);
};
app.get( '/product', getOne, transformProduct, sendProduct );
If you write middleware for your routes like this you'll end up with small building blocks you can easily reuse throughout your application.