I'm having this little issue/confusion here... I was actually able to get an individual article by their _id using findById(req.params.articleId)
my get request
router.get('/:articleId', function (req, res, next) {
var decoded = jwt.decode(req.query.token);
Article.findById(req.params.articleId, 'keyskeys')
.populate('user')
.exec( function (err, article) {
console.log('see out article too', article)
// if the ID is not found or invalid, return err
if (err) {
return res.status(500).json({
title: 'An error occured',
error: err
});
}
// if the article was not found anyways
if (!article) {
return res.status(500).json({
title: 'Article not found',
error: { message: 'Article was not found!' }
});
}
return res.json({
success: true,
message: 'successful :id',
article: article,
});
});
});
Postman is returning 200 ok, but the data returned isn't just what I wanted
its just returning the objectID whereas I need it to get the whole object of that particular Id to work with...
I'm kind of confused here, googled around, can't really get my hand on something...
postman is returning
{
"success": true,
"message": "successful :id",
"article": {
"_id": "5b0af26a0321733524c64c91"
}
}
its supposed to return something like
{
"_id" : ObjectId("5b0af26a0321733524c64c91"),
"favoritesCount" : 33,
"title" : "jfdkjkjgfkgfkll",
"description" : "lkfgmfglkgfklgfk",
"body" : "klmfl,,;lvk;lggpog,gf.,gf.gl.",
"username" : "qqqq",
"userId" : ObjectId("5b0af2500321733524c64c90"),
"__v" : 0
}
any help will be greatly appreciated
findById is a convenience method on the model that's provided by Mongoose to find a document by its _id. The documentation for it can be found here.
Example:
// Search by ObjectId
var id = "56e6dd2eb4494ed008d595bd";
UserModel.findById(id, function (err, user) { ... } );
Functionally, it's the same as calling:
UserModel.findOne({_id: id}, function (err, user) { ... });
for more information refer this Similar Question Link
Related
I'm building a todo app and in the database have an employee document containing 2 arrays (todo & done). The tasks are stored here, and I currently can add tasks to the arrays, but I'm having trouble figuring out how to get my API work to delete them.
Here's what my employee doc looks like
{"_id":{"$oid":"61797a3ed15ad09b88d167ab"},"empId":"1008","password":"password2","firstName":"test","lastName":"user","__v":5,"done":[],"todo":[{"_id":{"$oid":"61870bfe6ac33427b8406f7d"},"text":"testtask","id":"1"}]}
Currently I receive errors when trying to test using SoapUI, many similar to this "TypeError: Cannot read property 'findByIdAndDelete' of undefined" or Cannot DELETE /api/employees/1007/6184645df6bbd93340c0e390
Here's my delete API
*
* Delete task
*/
router.delete("/:empId/tasks/:id", async (req, res) => {
try {
Employee.findByIdAndDelete(
{ _id: req.params.id },
function (err, employee) {
if (err) {
console.log(err);
res.status(500).send({
message: "Internal server error: " + err.message,
});
} else {
console.log(employee);
console.log(
"Task with the id of" +
req.params.id +
" has been deleted successfully"
);
res.json(employee);
}
}
);
} catch (e) {
console.log(e);
res.status(500).send({
message: "Internal server error: " + e.message,
});
}
});
Currently, I can get messages to the console saying it's been deleted but it hasn't actually deleted in the database
Welcome to stackoverflow! You should use updateOne with $pull. Try:
Employee.updateOne({
empId: req.params.empId
}, {
$pull: {
todo: {
_id: req.params.id
}
}
})
Reference: https://stackoverflow.com/a/27917378/9459826
MongoDB docs: https://docs.mongodb.com/manual/reference/operator/update/pull/
I have my problem with the following function
export function updateLine(req: Request, res: Response) {
if (!req.params.id || !req.body) return res.status(400).send({ message: 'Client has not sent params' });
Line.findByIdAndUpdate(req.params.id, req.body, async (err, lineUpdated) => {
console.log("req.params.id", req.params.id)
console.log("lineUpdated", lineUpdated)
console.log("req.body", req.body)
if (err) return res.status(409).send({ message: 'Internal error, probably error with params' });
if (!lineUpdated) return res.status(404).send({ message: 'Document not found' });
if (req.params.id !== lineUpdated.id) await Key.updateMany({ 'line': req.params.id }, { 'line': lineUpdated._id }).exec(err => {
if (err) return res.status(500).send({ message: 'Key Internal Server Error' });
});
return res.status(200).send({ data: lineUpdated });
});
}
What I'm trying to do is just update the document req.params.id with what contains req.body
The responses to the console.log () shown are as follows
req.params.id ACCSEH
lineUpdated {
_id: 'ACCSEH',
name: 'Accesorios (SEH)',
started: 2020-04-21T20:25:10.395Z,
__v: 0
}
req.body { id: 'ACCSEJ', name: 'Accesorios (SEH)' }
I am doing something wrong?
I already know that lineUpdated will return the function to me before the change. I mean when I do the query to see the change nothing has changed
enter image description here
Referring to the documentation:
The field name _id is reserved for use as a primary key; its value
must be unique in the collection, is immutable, and may be of any type
other than an array.
You can not change _id field once it is inserted into the collection
When finding and updating by ID you can't give it an ID in the object - you need to give it an object that has some combination of the other items (name, started, _v).
When I add the line "{ upsert: true }", I got this error:
TypeError: callback.apply is not a function
// on routes that end in /users/competitorAnalysisTextData
// ----------------------------------------------------
router
.route('/users/competitorAnalysisTextData/:userName')
// update the user info (accessed at PUT http://localhost:8080/api/users/competitorAnalysisTextData)
.post(function (req, res) {
// use our user model to find the user we want
User.findOne({userName: req.params.userName}, function (err, user) {
if (err) res.send(err);
console.log(
'user.competitorAnalysis.firstObservation: %#',
user.competitorAnalysis.firstObservation,
);
// Got the user name
var userName = user.userName;
// update the text data
console.log('Baobao is here!');
user.update(
{
userName: userName,
},
{
$set: {
'competitorAnalysis.firstObservation': req.body.firstObservation,
'competitorAnalysis.secondObservation': req.body.secondObservation,
'competitorAnalysis.thirdObservation': req.body.thirdObservation,
'competitorAnalysis.brandName': req.body.brandName,
'competitorAnalysis.productCategory': req.body.productCategory,
},
},
{upsert: true},
);
// save the user
user.save(function (err) {
if (err) return res.send(err);
return res.json({message: 'User updated!'});
});
});
});
Without this line, there is no error. I'm new to nodejs, not very sure where the problem is.
Update
No error message now, but this part of the database is not updated with new data. The embedded document is still empty.
// on routes that end in /users/competitorAnalysisTextData
// ----------------------------------------------------
router
.route('/users/competitorAnalysisTextData/:userName')
// update the user info (accessed at PUT http://localhost:8080/api/users/competitorAnalysisTextData)
.post(function (req, res) {
console.log('1');
// Just give instruction to mongodb to find document, change it;
// then finally after mongodb is done, return the result/error as callback.
User.findOneAndUpdate(
{userName: req.params.userName},
{
$set: {
'competitorAnalysis.firstObservation': req.body.firstObservation,
'competitorAnalysis.secondObservation': req.body.secondObservation,
'competitorAnalysis.thirdObservation': req.body.thirdObservation,
'competitorAnalysis.brandName': req.body.brandName,
'competitorAnalysis.productCategory': req.body.productCategory,
},
},
{upsert: true},
function (err, user) {
// after mongodb is done updating, you are receiving the updated file as callback
console.log('2');
// now you can send the error or updated file to client
if (err) return res.send(err);
return res.json({message: 'User updated!'});
},
);
});
There are 2 ways to update documents in mongodb:
find the document, bring it to server, change it, then save it back to mongodb.
just give instruction to mongodb to find document, change it; then finally after mongodb is done, return the result/error as callback.
In your code, you are mixing both methods.
with user.save(), first you search the database with user.findOne, and pull it to server(nodejs), now it lives in your computer memory.
then you can manually change the data and finally save it to mongodb with user.save()
User.findOne({ userName: req.params.userName}, function(err, user) {
if (err)
res.send(err);
//this user now lives in your memory, you can manually edit it
user.username = "somename";
user.competitorAnalysis.firstObservation = "somethingelse";
// after you finish editing, you can save it to database or send it to client
user.save(function(err) {
if (err)
return res.send(err);
return res.json({ message: 'User updated!' });
});
the second one is to use User.findOneAndUpdate().. This is preferred, instead of user.findOne() then user.update(); because those basically searching the database twice. first to findOne(), and search again to update()
Anyway,the second method is telling mongodb to update the data without first bringing to server, Next, only after mongodb finish with its action, you will receive the updated-file (or error) as callback
User.findOneAndUpdate({ userName: req.params.userName},
{
$set: { "competitorAnalysis.firstObservation" : req.body.firstObservation,
"competitorAnalysis.secondObservation" : req.body.secondObservation,
"competitorAnalysis.thirdObservation" : req.body.thirdObservation,
"competitorAnalysis.brandName" : req.body.brandName,
"competitorAnalysis.productCategory" : req.body.productCategory
} },
{ upsert: true },
function(err, user) {
//after mongodb is done updating, you are receiving the updated file as callback
// now you can send the error or updated file to client
if (err)
res.send(err);
return res.json({ message: 'User updated!' });
});
You forgot to pass a callback to the update method
user.update(
{
$set: {
'competitorAnalysis.firstObservation': req.body.firstObservation,
'competitorAnalysis.secondObservation': req.body.secondObservation,
'competitorAnalysis.thirdObservation': req.body.thirdObservation,
'competitorAnalysis.brandName': req.body.brandName,
'competitorAnalysis.productCategory': req.body.productCategory,
},
},
{upsert: true},
function (err, result) {},
);
update method expects 3 arguments.
document update
options
callback
I am building backend with MEAN stack, but when I try to update document in the db i am getting an error:
topUp = function(name, amount, callback) {
User.updateOne(
{ "name" : name },
{ $set: { "wallet": amount } },
function(err, results) {
console.log(results);
callback();
});
};
TypeError: User.updateOne is not a function
But e.g. findOne() works fine:
User.findOne({
name: decoded.name
}, function(err, user) {
if (err) throw err;
i
f (!user) {
return res.status(403).send({success: false, msg: 'Authentication failed. User not found.'});
} else {
//res.json({success: true, info: {wallet: user.wallet, userPic: user.userPic}});
topUp(decoded.name, amount, function() {
User.close();
});
}
});
"User" is a Mongo model file.
I think it's not defined in the database driver that you might be using. I think you are using Mongoose and updateOne() is not available there. You cannot use all native mongodb functions with all drivers
There is an en existing enhancement request for this https://github.com/Automattic/mongoose/issues/3997 , but maybe the findByIdAndUpdate() method could be a close alternative.
apiRoutes.put('/intake/:id', function(req, res) {
var id = req.params.id;
Intake.findById({id, function(err, intake) {
if (err)res.send(err);
intake.check = true;
intake.save(function(err) {
if (err) {return res.json({success: false, msg: 'Error'});}
res.json({success: true, msg: 'Successful update check state.'});
});
}})
});
What's problem? In console i see ID, it's ok, but database have no change
Intake.findById(/*remove { here*/id, function(err, intake) {
if (err)res.send(err);
intake.check = true;
intake.save(function(err) {
if (err) {return res.json({success: false, msg: 'Error'});}
res.json({success: true, msg: 'Successful update check state.'});
});
})
You gave us too few information to help you. But I got some hints on how to find out what's going wrong: (I added example code a the end of my answer.)
Use a proper formatting of your code. Mistakes are easier to find.
Please avoid res.send(err). Most express apps provide an error to HTML Page translation at the end of the route pipe. This only works if you call res.next(err);. If your app does not provide error page generating at the end of the pipe then, you could use res.status(400).json({success: false, msg: err.message});.
After the use of res.send or res.next or res.json you have to end the execution of the function by return before one of these functions can be called a second time. This can be very complicated in case of nested or asynchrounous method calls. But in your example it's quite easy.
Use some log outputs to see which part of the code you reach and which not.
console.dir(<object>); prints out the structure of this object.
Hope this helps a little bit. ;-)
apiRoutes.put('/intake/:id', function(req, res)
{
var id = req.params.id;
Intake.findById(id, function(err, intake)
{
if (err)
{
res.next(err);
console.error(err);
return;
}
console.log("Modify check attribute");
intake.check = true;
console.dir(intake);
intake.save(function(err)
{
console.log("Intake save called!");
if (err)
{
console.error(err);
res.json({
success: false,
msg: 'Error'
});
return;
}
console.log("Success");
res.json({
success: true,
msg: 'Successful update check state.'
});
});
}})
});
you can use this
Intake.update({_id: req.params.id},
{
check : true
},
function(err){
if(err){
console.log(err);
res.status(400).send(err.errors);
}else{
res.status(200).end();
}
});