I am updating a record via Mongoose but when I try to not include a field by not including it in the properties object the field just gets set to empty.
My model:
var demo = new Schema({
name: String,
slug: String,
code: String,
details: String,
scripts: [],
css: [],
status: {
type: String,
default: "draft"
},
lastModifiedDate: {
type: Date,
default: Date.now
},
projectId: Schema.ObjectId
});
Where I'm saving:
Demo.find({ slug: req.params.demoSlug }, function(err,demos){
if(err){
console.log("Error retrieving demo from db");
res.send(500,err);
return;
}
demos[0].update({ _id:req.params.id },{
name: data.demoName,
slug: Utils.createSlug(data.demoName),
// code: data.demoCode,
details: data.demoDetails
}, someCallback);
});
As you can see the "code" field is commented out so why is the field value being overridden? Are there any flags I need to set when
It's not clear exactly what you're trying to do. You're searching for every document in a collection, but you're only updating one of them, which you're finding by _id. This looks like it can be done in one function, and you could be getting an error because you're calling update on a model that you returned. It looks like you should have written it like this:
Demo.update({ _id:req.params.id },{
name: data.demoName,
slug: Utils.createSlug(data.demoName),
// code: data.demoCode,
details: data.demoDetails
}, someCallback);
If you only want to update the document if its slug matches your demoSlug AND the _id matches, it would look like this:
Demo.update({ _id: req.params.id, slug: req.params.demoSlug },{
name: data.demoName,
slug: Utils.createSlug(data.demoName),
// code: data.demoCode,
details: data.demoDetails
}, someCallback);
If this still doesn't address your problem, hopefully it helps you explain more clearly what exactly you're looking for.
EDIT:
Another way to do this would be to use findOne and save. Try this:
Demo.findOne({ slug: req.params.demoSlug }, function(err, demo) {
if(err) {
console.log("Error retrieving demo from db");
res.send(500, err);
return;
}
demo.name = data.demoName;
demo.slug = Utils.createSlug(data.demoName);
demo.details = data.demoDetails;
demo.save(callback);
}
Something like that should hopefully work. If neither of these work, I suspect that the problem is in data or in the document you're finding.
Related
I am using Node.js, express, mongodb, and mongoose. I have two files: favorite and favorite-route.
"favorites" in the schema has multiple objects in it array. Given the mongodb assigned _id, I would like to create a delete method to gremove the specified object in the array.
Here is my schema in favorite:
userID:{
//type: String,
type: mongoose.Schema.Types.ObjectId,
ref: "user",
required: true,
unique: true
},
favorites:[{
publication: {
type:mongoose.Schema.Types.ObjectId,
ref: "Pet"
},
id: {
type: String,
required: true
},
comment: {
type: String,
required: true
}
}]
})
favoritesSchema.statics.deleteFavorite = async (favID)=>{
return await Favorite.findOneAndUpdate({favID})
}
This is my delete method in favorite-route file:
router.delete('/:favID', async (req,res)=>{
let doc = await Favorite.deleteFavorite(req.params.favID)
if(doc){
doc.splice(req.params.favID);
res.send(doc)
return;
}
res.status(404).send({error: "no se encontró esa publicación"})
})
And lastly, here is my http:
DELETE {{host}}/api/favorites/626eddd14762eb4ae4c77f9e
When i test this, it gives me the error:
TypeError: doc.splice is not a function
I'd appreciate any tips and insight. I have spent a while searching for answers but most suggested using $pull, which I am unsure how to implement in the delete method.
Thank you :)
you should do.
Favorite.updateOne(
{ userID: user._id }, // this is the query to find the desired favourite list
{ $pull: { favorites: { id : req.params.favID }} }, // this removes
);
So I am running into an issue trying to add comments to some data that is already in my mongoDB database. I want to make it so I can have comments be added and removed and updated for each account saved in my database and I am not sure what I am doing wrong necessarily. I have set up my front end to send in a new comment and all the data that needs to come along with it. it successfully gets to my back end, and at my backend it says it runs through and it gets saved but it doesnt, and when i reload the page the comments array in my data is still 0.
Account.findByIdAndUpdate(
{ _id: comment.accountId },
{
$push: {Account: { comments: comment }},
},
{ new: true, upsert: true }
).exec(function (err, task) {
if (err) {
return res
.status(400)
.send({ message: "Failed to add comment due to invalid params" });
}
console.log("successfully uploaded comment");
return res.status(200).send(task);
});
so here we are loading the specific account and then pushing that new comment to the comments array that is in my mongoose schema. when I take out the "Account: object and just ahve the object with comments:comment, it says there is an internal error on the back end not finding the parameter i guess, which would be comments array.
I dont know why that would be an issue. below is my mongoose schema as well.
const AccountSchema = new Schema({
username: {
type: String,
},
name: {
type: String,
},
date: {
type: Date,
default: Date.now,
},
description: {
type: String,
},
latitude: {
type: Number,
},
longitude: {
type: Number,
},
comments: [
{
id: Number,
text: String,
type: String,
date: Date,
replies: [{ id: Number, text: String, type: String, date: Date }],
},
],
});
Am I not setting up my schema correctly? or am I forgetting to add something somewhere. any help would be great, thank you!
It looks like your update query's $push specification is to blame. In the code, it says:
$push: {Account: { comments: comment }}
But your Account model does not have an "Account" field to push an object into. To insert a new element into the "comments" array, do this instead:
$push: { comments: comment }
Just wanted to post an update, I changed around the options on the findbyidandupdate, i added new and safe and upsert all true, and then low and behold I realized that my main issue was that my comments array in my schema was set to type: string, and not array. lol thanks for the help guys.
I'm trying to work on the "review" part of a review/rating website. We have a mongoose Schema which I'm pushing new reviews to.
This is the schema:
var WorkSchema = new mongoose.Schema({
title: String,
genre: String,
workType: String,
length: Number,
ageRange: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
manuscriptText: String,
critiques: [
{
reviewerName: String,
critique: String,
date: {
type: Date,
default: Date.now
}
}
],
ratingNumber: [Number],
ratingSum: {
type: Number,
default: 0
},
date: {
type: Date,
default: Date.now
}
});
When a user submits a new review, this is the post route. It is pushing the critique to the array of critiques associated to the work (confirmed by searching in mongodb), but I keep getting a reference error that "critique" is not defined in the render. I need to re-render the work page so that the reviewer can see that their critique has been added and displays on the front end. Not sure why this is happening since 'critiques' is practically everywhere.
router.post('/:id', function(req, res) {
Work.findByIdAndUpdate(req.params.id,
{
$push:
{
critiques: {
reviewerName: req.user.username,
critique: req.body.critique
}
}
}, { new: true}).populate('works', 'critiques').exec(function(err, foundWork) {
if (err) {
console.log(err);
} else {
res.render('work',
{
user: foundWork,
title: foundWork.title,
critiques: critiques,
currentUser: req.user,
work: foundWork
}
);
}
});
});
while you are rendering all the values after update.
you are doing critiques: critiques,
while critiques is not defined as a variable.
now you have 2 options , first is you can just show the full critiques array. as it is coming from the database.[may be you can do some operations with that data if need.]
like critiques: foundWork.critiques.
or otherwise yoou can just show the data you are inserting at that time as
critiques : req.body.critiques
like below:
Take from DB as it is
res.render("work", {
user: foundWork,
title: foundWork.title,
critiques: foundWork.critiques,
currentUser: req.user,
work: foundWork
});
take from body pushing the current element
res.render("work", {
user: foundWork,
title: foundWork.title,
critiques: req.body.critiques,
currentUser: req.user,
work: foundWork
});
I have the following schemas defined:
module.exports.contact=Schema({
_id:Number,
name: String,
email: String,
contactNumber: String,
company:String,
_invoices:[{ type: Schema.Types.ObjectId, ref: 'invoice' }],
},{strict:false});
module.exports.invoice=Schema({
_contact: { type : Number, ref: 'contact'},
_id:Number,
invoiceNumber:Number,
},{strict:false});
And following data is inserted in mongodb:
//CONTACT COLLECTION
{_id:1,name:"Mrinal Purohit",email:"mrinal#mrinalpurohit.com",contactNumber:"+919016398554",company:""}
//INVOICE COLLECTION
{ _id:1, invoiceNumber:3 , _contact:1 }
Only one document is there in the respective collections. Now i attempt this:
models.contact.find().populate('_invoices').exec(function(err,data){
console.log(data);
res.send(data)
});
I get the following:
[ { _id: 1,
name: 'Mrinal Purohit',
email: 'mrinal#mrinallabs.com',
contactNumber: '+919016398554',
company: '',
__v: 0,
_invoices: [] } ]
I actually expected the invoices to be populated in the array. Is there something wrong with the schema definition?
I am unable to completely understand the .populate function of mongoose :(
Your _id type is mismatched
In your invoice schema _id is defined as a Number. However in your definition of _invoices in the contact schema, you've selected the Schema.Types.ObjectId type
Try changing the type of _invoices to Number, e.g.
module.exports.contact=Schema({
_id:Number,
name: String,
email: String,
contactNumber: String,
company:String,
_invoices:[{ type: Number, ref: 'invoice' }],
},{strict:false});
Alternatively, you can let Mongoose set _id for you by omitting the _id property in your schemas (so you can leave _invoices unchanged). It would save you a bit of work in generating unique IDs and it also has a bunch of other useful properties (like the embedded timestamp)
Update
damphat is also correct in pointing out the other error (which I missed). According to the data you're inserting, you've haven't pushed the _id of your new invoice into the relevant contact document
Here's a sketch of how to create an invoice while properly updating the relevant contact
Invoice.create(invoiceAttributes, function (err, invoice) {
if (err) // Handle your error
Contact.findOne({ _id: invoiceAttributes._contact}, function (err, contact) {
if (err) // Handle your error
contact._invoices.push(invoice._id); // The important step you were missing
contact.save(); // Insert your callback
});
});
Just add 1 line _invoices: [1] to the contact document:
{
_id: 1,
name: "Mrinal Purohit",
email: "mrinal#mrinalpurohit.com",
contactNumber: "+919016398554",
company: "",
_invoices: [1]
}
and correct the typo in your contact schema as well.
I am building an API in node.js which uses mongodb and mongoose. Currently I have an embedded document within an embedded document (Schema within a Schema) that is simply not persisted to the database, and I have tried all I can but no luck.
I have the Schema's defined in mongoose as:
var BlogPostSchema = new Schema({
creationTime: { type: Date, default: Date.now },
author: { type: ObjectId, ref: "User" },
title: { type: String },
body: { type: String },
comments: [CommentSchema]
});
var CommentSchema = new Schema({
creationTime: { type: Date, default: Date.now },
user: { type: ObjectId, ref: "User" },
body: { type: String, default: "" },
subComments: [SubCommentSchema]
});
var SubCommentSchema = new Schema({
creationTime: { type: Date, default: Date.now },
user: { type: ObjectId, ref: "User" },
body: { type: String, default: "" }
});
And the code I execute is as follows:
// Create a comment
app.post("/posts/:id/comments", function(req, res, next) {
Posts.find({ _id : req.params.id }, function(err, item){
if(err) return next("Error finding blog post.");
item[0].comments.push(new Comment(JSON.parse(req.body)));
item[0].save(); // <= This actually saves and works fine
respond(req, res, item[0].comments, next);
});
});
// Create a subcomment
app.post("/posts/:id/comments/:commentid/subcomments", function(req, res, next) {
Posts.find({ _id : req.params.id }, function(err, item){
if(err) return next("Error finding blog post.");
item[0].comments[req.params.commentid - 1].subcomments.push(new SubComment(JSON.parse(req.body)));
item[0].save(); // <= This completes (without error btw) but does not persist to the database
respond(req, res, item[0].comments[req.params.commentid - 1].subcomments, next);
});
});
I can create Blog Posts with comments without problem, but for some reason I can not create subcomments on a comment. The Blog Post document actually has the comments and subcomments attached when printing to the console during execution - only it does not save to the database (it saves the Blog Post with a comment, but no subcomments).
I have tried to "markModified" on the comments array, but no change:
Posts.markModified("comments"); // <= no error, but also no change
...
Posts.comments.markModified("subcomments"); // <= produces an error: "TypeError: Object [object Object] has no method 'markModified'"
Problem since solved. I was given the answer by Aaron Heckmann over on the mongoose Google Group:
Always declare your child schemas before passing them to you parent schemas otherwise you are passing undefined.
SubCommentSchema should be first, then Comment followed by BlogPost.
After reversing the schemas it worked.
I thing the updating of a document is not an important issue as the embedded documents are also fully capable of any services.