Node.js/mongoose - sub-document in a array won't delete/remove - javascript

So this is my first on-my-own node.js project after finishing up an online Bootcamp. Running into trouble removing a sub-doc in my array. Here's some code, I hope I provide enough info for someone to help me out.
models:
var productSchema = new mongoose.Schema({
name: String,
type: String,
location: String
});
var clientSchema = new mongoose.Schema({
name: String,
address: String,
contactinfo: String,
products:[]
});
And this is my post route that is adding the product to the client, which works great:
//Add New Product
app.post("/clients/:id/products", middleware.isLoggedIn, function(req, res){
Client.findById(req.params.id, function(err, client) {
if(err){
console.log(err);
req.flash('error', "We cannot find the Client!!!");
return res.redirect("/clients/" + req.params.id + "/products/new");
}
Product.create(req.body.product, function(err, product){
if(err){
req.flash('error', "There was an error adding the product to the user, try again");
} else{
client.products.push(product);
client.save();
req.flash('success', "You have added a New Product");
res.redirect('/clients/' + req.params.id +'/products/new');
}
});
});
});
My delete route is my problem child. It deletes the product, but I can't seem to get it out of the array at all. I did some research and tried the following:
client.products.find({_id:req.params.product_id}).remove()
client.products.id(req.params.product_id).remove()
client.products.pull({_id: req.params.product_id})
client.find({products:{_id: req.params.product_id}}).remove()
using client.save() right after each
I get errors or it deletes the client,
but never deletes the product from the array. Any help would be great or if there's a better way to do this, that would be great too. Tried for a week before turning for help, so open for feedback from skilled developers.
oh here is my last delete route, think I'm going to disable until I found a fix , so I can continue my project.
//Delete a Product
app.delete("/clients/:id/products/:product_id", middleware.isLoggedIn, function(req, res){
Product.findByIdAndRemove(req.params.product_id, function(err){
if(err){
console.log(err);
} else {
console.log("Should be deleted now!");
Client.findById(req.params.id, function(err, client) {
if(err){
console.log(err);
}
console.log(client.products.length);
client.find({products: {_id: req.params.product_id}}).remove();
client.save();
console.log(client.products.length);
res.redirect("/clients/");
});
}
});
});
The length I used to see if anything changed and it never did.

First, your method requires a objectID. Try like this and see if it works:
Product.findByIdAndRemove(ObjectId(req.params.product_id)

Nevermind, it seems that the issue here is my code. Instead of pushing a ref in my client schema for the products array I pushed the product info directly in the array. Then in my app in one area I'm accessing the data from the Product collection, but in another part of my app I'm accessing the same info from the client collection through the products array. Based on my training(Other course apps I created) it seems that the ref doesn't get remove it just can't refer to the collection since it's no longer in the collection.
Thank you Laurentiu & Federico for looking at this and providing some helpful information. sorry about any headaches this may have caused you.

Looked into documents and it won't delete. It deletes the content not the ID, so it stays in the MongoDB Database.
router.delete('/inventario/:_id', function(req, res){
Propiedades.findByIdAndDelete(req.params._id, function(err,){
if (err){
res.redirect('/inventario/');
} else {
res.redirect('/inventario/');
}
})
});

Related

Confusing error message using updateOne() function on a mongodb collection

To summarize, I have a mongodb database with a 'groupcollection' in it. One of the attributes is called 'deleted' and it has values either true or false. I want to update the value of 'deleted' for a specific document using 'groupname' as the query attribute. However, when I try the code below I receive the error "TypeError: collection.updateOne is not a function"
router.post('/deletegroup', function(req, res) {
var db = req.db;
var collection = db.get('groupcollection');
var filter = {"groupname" : req.body.groupname};
var updates = { $set: {"deleted" : true} };
collection.updateOne(filter, updates, function(err) {
if (err) {
// If it failed, return error
res.send("There was a problem deleting the group from the database.");
}
else {
// And forward to success page
res.redirect("grouplist");
}
});
});
I've read the documentation on updateOne() for Node.js from mongoDB and I can't seem to figure out the reason for the error. Also, I am still very new to javascript/nodejs/mongo so I would greatly appreciate more informative answers!
The solution I came up with was using unique IDs for each group and instead of using updateOne() just using update() and having the unique ID as the query to make sure that I don't modify groups with the same name

Error with get request for users

When using a get request for all the users in my database (see code below) i only get the "first" user in the database. If i instead try to use the "findOne"-method i get the same user as before no matter what i put in (the username doesn't even have to be in the db it still gives me the same user). I've been trying to understand why this isn't working but can't find any problems with the code. Could it be a problem with db settings or something similar? All help is appreciated!
In AuthController:
// Get all users
AuthController.allusers = function(req, res) {
User.find({}, function(err, users) {
}).then(function(users) {
res.json({users: users});
});
}
In routes:
// GET Routes.
router.get('/users', AuthController.allusers);
Since you are using Sequelizejs, you might want to do findAll.
AuthController.allusers = function(req, res) {
User.findAll().then(function (users) {
res.send({users: users});
}
}
According to the docs:
find - Search for one specific element in the database
findAll - Search for multiple elements in the database

associating a GridFS-Stream file to a Schema with Mongoose

I am writing an API for my application, using Mongoose, Express, and GridFS-Stream. I have a Schema for the articles the user will create:
var articleSchema = mongoose.Schema({
title:String,
author:String,
type: String,
images: {type: Schema.Types.ObjectId, ref: "fs.files"},
datePublished: { type: Date, default: Date.now },
content: String
})
var Article = mongoose.model("article", articleSchema, "articles");
and my grid-fs set up for when a user uploads an image:
api.post('/file', fileUpload.single("image"), function(req, res) {
var path = req.file.path;
var gridWriteStream = gfs.createWriteStream(path)
.on('close',function(){
//remove file on close of mongo connection
setTimeout(function(){
fs.unlink(req.file.path);
},1000);
})
var readStream = fs.createReadStream(path)
.on('end',function(){
res.status(200).json({"id":readStream.id});
console.log(readStream);
})
.on('error',function(){
res.status(500).send("Something went wrong. :(");
})
.pipe(gridWriteStream)
});
Right now it's set up to when the user chooses an image, it automatically uploads it via gridfs-stream, puts it in a temp folder, then deletes it when it is uploaded to the mongo server, and in the console returns what the ObjectId is. Well thats all find and dandy, but we need to associate this ID with the articleSchema, so when we call that article in the app, it will display the associated image.
on our creation/update of an article when the user hits submit:
createArticle(event) {
event.preventDefault();
var article = {
type: this.refs.type.getValue(),
author: this.refs.author.getValue(),
title: this.refs.title.getValue(),
content: this.refs.pm.getContent('html')
};
var image = {
images: this.refs.imageUpload.state.imageString
};
var id = {_id: this.refs.id.getValue()};
var payload = _.merge(id, article, image);
var newPayload = _.merge(article, image)
if(this.props.params.id){
superagent.put("http://"+this.context.config.API_SERVER+"/api/v1.0/article/").send(payload).end((err, res) => {
err ? console.log(err) : console.log(res);
});
} else {
superagent.post("http://"+this.context.config.API_SERVER+"/api/v1.0/article").send(newPayload).end((err, res) => {
err ? console.log(err) : console.log(res);
this.replaceState(this.getInitialState())
this.refs.articleForm.reset();
});
}
},
So what I need it to do, is call the ID, of the image I just uploaded to the images section of my schema when the user hits submit on the creation of an article. I've tried doing a readstream on submit, but again, the problem is I can't get the ID, or the filename, to be able to associate it.
They are getting stored in the mongo database, it creates fs.files and fs.chunks, but for the life of me I can't figure out how to get that data and attach it to a schema, or just even get the data out, without knowing the ObjectId.
So how do I call out the objectid from fs.files or fs.chunks to attach it to the schema? and in the schema how do I reference the fs.files or chunks? so it knows what the objectid is associated with?
I can provide anymore data, if what I have is to vague, I have a nasty habit of doing that. sorry.
So I ended up solving my problem, might not be the best solution, but it works until I can get a better solution.
in the API changed
res.status(200).json({"id":readStream.id});
to
res.status(200).send(readStream.id);
in my component, I then set the state to the response.body, which will set the state of the id of the image uploaded. So in the main view, i reference the image uploading component, and set the image state of my view to the id state of my component, and viola, I now have the id in my database, associated with the newly created article.
the problem i then ran into was, it didn't know what to reference. so I attached the API URL to the id, and it acts like it is referencing a URL img, and renders the image correctly.
Again, this may not be the best way to go about this, in fact, I am pretty sure it isn't, but It is whats working for now until I can either reference the database correctly, or create a new component that just stores all the images on server and reference them that way, much like wordpress.

Proper Way To Ensure All Save Methods Work: node.js, MongoDB

I am quite new to MongoDB and Node.JS, and I have a question about what is the proper way to implement multiple save calls in the same route and ensure that they all work, or none do. What I want, is that if one save fails, they both do. Here is some code. It works as expected with no problems, but I have a feeling that it is bad practice.
My Post Schema, as you can see, it is just some text, and then an array of pointers to another object called Comment.
var postSchema = mongoose.Schema({
text: String,
comments : [{
type : mongoose.Schema.Types.ObjectId,
ref : "Comment"
}]
});
My Comment Schema. All it is, is just some text.
var commentSchema = mongoose.Schema({
commentText: String
});
Now, here is my route...
apiRoutes.post("/testCreateComment", function(request, response, next){
var commentText = request.body.commentText;
var testID = request.body.testID
if (!commentText || !testID) //ensures all data is there.
return next(new Error("Not all the information required was provided."));
var newComment = new Comment({
commentText : commentText
})
newComment.save(function(err) { //first save the new TestComment.
if (err) return next(err);
Post.findById(testID, function(err, found){ //second find the Post object.
if (err) return next(err);
found.comments.push(newComment)
found.save(function(err){ //third, save the Post object with the comment added to the array.
if (err) return next(err);
response.json(newComment.getReturn()); // returns some data to be sent
})
})
})
})
In this route, there are three methods that must be successful for the entire operation to work. Now, for instance, save that the first save works, but for whatever reason the findById is unsuccessful. In this circumstance, I would have a comment floating around in the database that is useless.
My question is, what is the proper way to ensure that all three operations are successful and ensure that the problem described above cannot possibly happen?

How to delete document from mongoDB collection using the document's ID?

I am trying to remove a document from a mongoDB collection by finding the document in the collection using an id. Below is a snippet of my code and it says that the note was successfully deleted but when I go back to where all the notes are displayed, the note that was supposedly deleted is still there.
router.post('/delete', function(req, res) {
notesCollection.remove(prevID, function(err, records){
if(err){
res.render("deleteFail.jade");
}
else{
res.render("deleteSuccess.jade");
}
});
});
Where prevID is the _id of the note currently trying to be deleted. Any help is greatly appreciated! Thanks
Are you using mongoose? I am pretty certain the first argument has to be a query object, e.g. { _id: prevId } and not just the id directly.

Categories