Why can i not increment this property? - node.js

I want to make a route in NodeJS which increment the property of a subdocument but I don't know how to do it and the way I am doing it now does not seem to work.
blogPost model
const BlogPostSchema = new Schema({
content: {
type: String,
validate: {
validator: (content) => content.length > 5,
message: 'Content must contain at least 6 characters.'
},
required: [true, 'Content must be filled in.']
},
rating: Number,
title: String,
user: { type: Schema.Types.ObjectId, ref: 'user' },
board: {type: Schema.Types.ObjectId, ref: 'board'},
comments: [commentSchema]
});
const BlogPost = mongoose.model('blogPost', BlogPostSchema);
module.exports = BlogPost;
comment schema
const CommentSchema = new Schema({
content: {
type: String,
validate: {
validator: (content) => content.length > 5,
message: 'Content must contain at least 6 characters.'
},
required: [true, 'Content must be filled in.']
},
user: { type: Schema.Types.ObjectId, ref: 'user' },
rating: Number
});
module.exports = CommentSchema;
NodeJS route
routes.put('/blogPosts/:id/comment/:idm', function(req, res) {
const blogPostId = req.param('id');
const commentId = req.param('idm');
BlogPost.findById(blogPostId)
.then((blogPost) => {
blogPost.comments.findByIdAndUpdate({_id: commentId}, {$inc: {rating: 1}});
})
.then((blogPost) => res.status(200).json({
'status': 'Comment rating is increased.'
}))
.catch((error) => res.status(400).json(error))
});
This is the response Postman
All help is appreciated.

Well the promise hasn't been resolved, so what you can do is use async await functions or JavaScript generators which will make the client wait till the rating is incremented and the results json is sent.
Here's a tutorial on async-await and generators.

Related

mongoose foreign key some field are disabled (not show when call api)

I have two schema:
(1) authSchema
(2) bookSchema
const authSchema = new mongoose.Schema({
name: {
type: String,
required: true
}
});
const bookSchema = new mongoose.Schema({
authors: [{
authId: {
type: Schema.Types.ObjectId,
ref: "auth",
required: true
}
}],
title: {
type: String,
required: true,
}
});
And my get route
// Auth = new mongoose.model("auth", authSchema);
app.get("/", (req, res, next) => {
Auth.find({})
.select({
__v: 0,
_id: 0,
})
})
Then the output is:
pastebin link
*** But I want to data the below format
pastebin link
What changes make this output!
thanks!

Linking models in MongoDB

I have a model to create an article, and I want to save the id of the user that created that article also. I am doing this, but I have an error. I really appreciate any help!
let articleSchema = new Schema({
title: {
type: String,
required: true
},
description: {
type: String,
},
markdown: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now
},
user: {type: Schema.ObjectId, ref: 'User'}
});
module.exports = mongoose.model('Article', articleSchema);
let userSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
},
role: {
type: String,
default: 'USER_ROLE',
enum: validRoles
}
});
userSchema.plugin(uniqueValidator, {message: '{PATH} must be unique'});
module.exports = mongoose.model('User', userSchema);
And in the post method of the article I have this:
How can I access the user??
const article = new Article({
title: body.title,
description: body.description,
markdown: body.markdown,
user: req.user._id
});
I think that there's a problem in your article schema. Try to change
user: {type: Schema.ObjectId, ref: 'User'}
to
user: {type: Schema.Types.ObjectId, ref: 'User'}
Then, to display the author information try this in your routes file:
app.get('your-get-article-route', async (req, res) => {
try {
const articles = await Article.find().populate('user');
// other pieces of code if needed
res.status(200).json({ articles });
} catch (error) {
res.status(400).json({ message: 'an error occured!'});
)
If you're not familiar with async/await, you can do it with promises:
app.get('your-get-article-route', (req, res) => {
const articles = Article.find().populate('user').then((articles) => {
// other pieces of code if needed
res.status(200).json({ articles });
}).catch((error) => {
res.status(400).json({message: 'an error occured'}
);
)

Mongoose Populate not working while querying data

I have 2 models, category and story.
Story contains reference id of the category.
In controller story, I have a function mystories which should fetch all the story records of particular user along with category information.
I am getting data from story collection but not from category collection.
The result which I receive is something like this:
category_id: "5d10978c8e0f5d5380fdb3e6"
created_at: "2019-06-25T10:02:47.637Z"
created_by: "5d1066fba920ef2ccfe68594"
image: "uploads/1561456967615_164.jpg"
published: "no"
status: "pending"
text: "<p><strong>Fashion</strong> is a popular aesthetic expression in a certain time and context, especially in clothing, footwear, lifestyle, accessories, makeup, hairstyle and body </p>"
title: "New fashion"
__v: 0
_id: "5d11f14757f8616041616217"
It should however return category collection information instead of
category id.
Category model:
const mongoose = require('mongoose');
const categorySchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
name: {
type: String,
required: true,
unique: true
},
status: {
type: String,
required: true,
enum: ['active','inactive','deleted']
},
created_at: { type: Date, default: Date.now },
created_by: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true},
});
module.exports = mongoose.model('Category', categorySchema);
Story model:
const mongoose = require('mongoose');
const storySchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
title: {
type: String,
required: true
},
text: {
type: String,
required: true
},
category_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Category',
required: true
},
image: {
type: String,
required: true
},
status: {
type: String,
required: true,
enum: ['pending','approved','deleted']
},
published: {
type: String,
required: true,
enum: ['yes','no']
},
created_at: { type: Date, default: Date.now },
created_by: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true},
});
module.exports = mongoose.model('Story', storySchema);
Controller code:
const mongoose = require('mongoose');
const Story = require('../models/story');
const Category = require('../models/category');
exports.mystories = async (req, res, next) => {
const user_id = req.userData.id;
const all_stories = await Story
.find({ created_by: user_id})
.populate('name','category')
.sort({ created_at: -1 })
.exec();
if(all_stories.length > 0) {
return res.status(200).json({
response: all_stories
});
}else {
return res.status(200).json({
response: []
});
}
};
exports.add_story = (req, res, next) => {
console.log(req.file);
const story = new Story({
_id: new mongoose.Types.ObjectId(),
title: req.body.story_title,
text: req.body.story_text,
category_id: req.body.story_category,
image: req.file.path,
status: 'pending',
published: 'no',
created_by: req.userData.id
});
story
.save()
.then(result => {
console.log(result);
res.status(200).json({
response: 'added_story'
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
})
});
};
populate takes the field name as it is given in story schema.
it should be :
.populate({path: 'category_id', select: 'name'})

How do I increment a property of a subdocument in Mongoose?

I am making a route in NodeJS using Mongoose which increments the rating of a subdocument of an object. I will post the models and route code below. When I execute the query in Postman, I get an empty json object back and a 400 error. This means somewhere in the query I am doing something wrong.
blogPost model
const BlogPostSchema = new Schema({
content: {
type: String,
validate: {
validator: (content) => content.length > 5,
message: 'Content must contain at least 6 characters.'
},
required: [true, 'Content must be filled in.']
},
rating: Number,
title: String,
user: { type: Schema.Types.ObjectId, ref: 'user' },
board: {type: Schema.Types.ObjectId, ref: 'board'},
comments: [commentSchema]
});
const BlogPost = mongoose.model('blogPost', BlogPostSchema);
module.exports = BlogPost;
comment schema
const CommentSchema = new Schema({
content: {
type: String,
validate: {
validator: (content) => content.length > 5,
message: 'Content must contain at least 6 characters.'
},
required: [true, 'Content must be filled in.']
},
user: { type: Schema.Types.ObjectId, ref: 'user' },
rating: Number
});
module.exports = CommentSchema;
NodeJS route
routes.put('/blogPosts/:id/comment/:idm', function(req, res) {
const blogPostId = req.param('id');
const commentId = req.param('idm');
BlogPost.findById(blogPostId)
.then((blogPost) => {
blogPost.comments.findByIdAndUpdate({_id: commentId}, {$inc: {rating: 1}});
})
.then((blogPost) => res.status(200).json({
'status': 'Comment rating is increased.'
}))
.catch((error) => res.status(400).json(error))
});
This is the response PostMan
All help is appreciated.
This was the error:
BlogPost.findById(blogPostId)
.then((blogPost) => {
blogPost.comments.findByIdAndUpdate({_id: commentId}, {$inc: {rating: 1}});
})
.then((blogPost) => res.status(200).json({
'status': 'Comment rating is increased.'
}))
Should be:
BlogPost.update({_id: blogPostId, 'comments._id': commentId}, {$inc:{'comments.$.rating':1}})
.then((blogPost) => res.status(200).json({
'status': 'Comment rating is increased.'
}))

Why do I get a castError when I try to push an object to an array in MongoDB and Nodejs?

I have a mongoDB and I am trying to make a Nodejs server to manipulate the data in the database. I get a castError when I try to push a Comment to the Comments array in a BlogPost object.
Source code below, please tell me if you're missing important information.
Thanks in advance!
The route:
routes.post('/comments/push/:id', function(req, res) {
const blogPostId = req.param('id');
const commentProps = req.body;
BlogPost.findById(blogPostId)
.then((blogPost) => {
blogPost.comments.push(commentProps);
return blogPost.save();
})
.then((blogPost) => res.status(200).json({
'status': 'Comment is deleted.',
'comment': blogPost
}))
.catch((error) => res.status(400).json(error)) });
The BlogPost schema:
const BlogPostSchema = new Schema({
content: {
type: String,
validate: {
validator: (content) => content.length > 5,
message: 'Content must contain at least 6 characters.'
},
required: [true, 'Content must be filled in.']
},
rating: Number,
user: { type: Schema.Types.ObjectId, ref: 'user' },
board: {type: Schema.Types.ObjectId, ref: 'board'},
comments: [{
type: Schema.Types.ObjectId,
ref: 'comment'
}]
});
The Comment schema:
const CommentSchema = new Schema({
content: {
type: String,
validate: {
validator: (content) => content.length > 5,
message: 'Content must contain at least 6 characters.'
},
required: [true, 'Content must be filled in.']
},
user: { type: Schema.Types.ObjectId, ref: 'user' },
rating: Number
// board: Board
});
Here is the error in postman:
postman screen
Help would be greatly appreciated!
first make sure what's you are receiving in req.body, it's not good
to store directly from req.body.
second ref. comments Schema aspect a objectId while req.body is
Object itself. i'm not sure what are you going to do but it
something like blogPost.comments.push(req.body.someValidId);
third why 2 queries for simple update. you can use $push, $addToSet to push directly to comments or $pull to remove from comments.
BlogPost.findOneAndUpdate({
_id:blogPostId
}, {
$addToSet:{
comments : someValidId
}
}, {
new :true,
upsert:false
})
.then((blogPost) => {
res.status(200).json({
'status': 'Comment is deleted.',
'comment': blogPost
})
})
.catch((error) =>
res.status(400).json(error))
});

Resources