mongoose findOne work using id instead of _id - node.js

I was stuck for a while when I do _id in findOne function I got empty result.
exports.getUser = function(req, res) {
User.findOne({id: req.params.id}, function(err, user) {
if (err) {
return res.status(400).send({
msg: err
})
} else {
return res.json({status:1, data: user})
}
})
}
Above code worked but I'm curious why this won't work
...
User.findOne({_id: req.params.id}, function(err, user) {
...
I think I have to parse req.params.id with ObjectId function, but is there any global method that ignore this rule? for me it make sense just use _id: myId

Related

Deleting the model data through lodash and save() not persisting model in mongodb

I am trying to remove one object from the User collection like this
router.post('/accept-trades', function (req, res, next) {
const {senderName, receiverName, senderId} = req.body;
const user = req.user;
console.log(senderName, receiverName);
if (senderName) {
User.findOne({ name: senderName })
.then(sender => {
_.remove(user.receivedTradeRequest, {username: senderName});
_.remove(sender.sentTradeRequest, {username: receiverName});
console.log('user.receivedTradeRequest', user.receivedTradeRequest);
console.log('\n\nuser.sentTradeRequest', user.sentTradeRequest);
async.parallel([
function (cb) {
user.save()
.then(isSave => {
cb(null, true);
})
.catch(err => {
cb(err, null);
});
},
function (cb) {
sender.save()
.then(isSave => {
cb(null, true);
})
.catch(err => {
cb(err, null);
});
}
], (err, results) => {
if (err) {
return res.status(500).json({
message: 'Error: Trade is invalid as Card is already traded!',
});
}
res.send('done');
//res.redirect('/trade');
});
})
.catch(err => {
throw err;
});
} else {
return res.status(500).json({
message: 'Only accessible to logged in users!',
});
}
});
Here, user is accessed by req.user (i'm using passport).
When i log the user after removal, user.receivedTradeRequest and sender.sentTradeRequest printing empty array which is the correct behaviour.
But when i see the mongodb the array still present for the username.
Could you please suggest what is wrong with the code ?
PS: I know about the mongodb $pull for removal. I am doing some other computation on the user data so had to do with above approach.
I was able to solve it by re-assigning the array after removing the element. Used _.filter instead of _.remove solves the problem.
One thing i don;t understand is the lodash _.remove update the original array after deletion but that clearly is not the case here.

Nodejs Mongodb: findByIdAndUpdate not returning correct error

My put request is returning success when it should be returning an error. I do not even have a User collection in my MongoDb yet (therefore no valid id's either). But when I make this call it returns success. Why is findByIdAndUpdate not returning any error?
app.put(path, (req, res) => {
User.findByIdAndUpdate(req.body.id, req.body, {}, (err, doc) => {
if (err) return res.status(400).send(err);
res.status(200).send({ response: 'success' });
})
});
Try this:
app.put(path, (req, res) => {
User.findByIdAndUpdate(req.body.id, req.body, {}, (err, doc) => {
if (err) {
return res.status(400).send(err);
} else {
if(doc){
return res.status(200).send({ response: 'success' });
} else {
return res.status(400).send({response:'false',message:'Not Found!'});
}
}
});
});
By default, when no matching document found, mongoose return null and we need to do something with that null value.

Mongoose Put method CastError

With the following put mongoose method, I get an error in postman if I do not fill all key/value pair!
app.put('/api/users/:user_id', function(req, res) {
users.update({
id_userLogin : req.body.id_userLogin,
userName : req.body.userName,
email : req.body.email,
password : req.body.password,
userNotes: req.body.userNotes
}, function(err, user) {
if (err)
res.send(err);
users.find(function(err, users) {
if (err)
res.send(err)
res.json(users);
});
});
});
It works fine if I put all key/value pair but if it miss one pair, I get
"message": "Cast to string failed for value \"undefined\"",
"name": "CastError",
"type": "string"
if I add || "" for each params we can update the user with all empty params. In fact if a params is not updated we should keep the initial value
Any help would be appreciated
You should check all request parameters for plausibility and discard the request if it is malformed. For non-mandatory params (e.g., userNotes), you can set the param to an empty string if it is undefined:
app.put('/api/users/:user_id', function(req, res) {
if (!req.id_userLogin || userName || password) {
return res.send('Malformed request', 400);
}
users.update({
id_userLogin : req.body.id_userLogin,
userName : req.body.userName,
email : req.body.email,
password : req.body.password,
userNotes: req.body.userNotes || ""
}, function(err, user) {
if (err)
res.send(err);
users.find(function(err, users) {
if (err)
res.send(err)
res.json(users);
});
});
});
I move the code to for controller
exports.update = function(req, res, next) {
var id = req.params.id
User.findByIdAndUpdate(id, req.body, function(err, user) {
if (err) {
return next(err);
} else {
res.json(user);
}
});
}
and for the route
app.route('/api/users/:id').put(users.update);
which fix the issue. With this method you can update one of the params

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

Avoid extra query with Mongo and Express in PUT

I'm updating a record in Mongo with Mongoose/Express:
app.put('/loggedIn/:id', function(req, res) {
if (req.user._id == req.params.id) {
User.update({
_id: req.user._id
}, {
$set: {
interests: req.body.interests
}
}, function(err, num) {
if (err) return err;
User.findById(req.user._id, '_id username interests', function(err, user) {
if (err) return;
res.json(user);
});
});
} else {
console.log('fail');
}
});
How can I avoid doing the second query in the callback of the update(), seems a lot just to return the newly updated document.
If you're always updating only one document you can use findByIdAndUpdate (or findOneAndUpdate), which updates the document if found and returns it to the callback:
app.put('/loggedIn/:id', function(req, res) {
if (req.user._id == req.params.id) {
User.findByIdAndUpdate(req.user._id, {
$set: {
interests: req.body.interests
}
}, function(err, user) {
if (err) return;
res.json(user);
});
} else {
console.log('fail');
}
});
I think you can get the raw Mongo response as the 3rd update callback argument. Check if this contains what you want. Otherwise, try passing the option { raw: true }.
See http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
You could use findByIdAndUpdate instead of a separate find and update.
I also sometimes do User.Find() and then inside the success callback Doc.save(). That lets you do more complex things between if it's not just a straight update from the request.

Resources