I am creating an application using Nodejs and React, but the comment function does not work. I do not know the cause.
Error :
board validation failed: comments.0.content: Path content is required.
I don't know why this is not working. What mistake did I make?
route/api/board.js
router.post(
'/:id/comments',
[
auth,
[
check('content', 'input your content. ')
.not()
.isEmpty()
]
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() }, 'isEmpty');
}
try {
const user = await User.findById(req.user.id).select('-password');
const board = await Board.findById(req.params.id);
const newComment = new Board({
content: req.body.content,
user: req.user.id
});
board.comments.unshift(newComment);
await board.save();
res.json(board.comments);
} catch (err) {
console.error(err.message);
res.status(500).send('Server error!!');
}
}
);
models/Board.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const BoardSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
view_count: {
type: Number,
default: 1
},
created_at: {
type: Date,
default: Date.now
},
likes: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user'
}
}
],
comments: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
content: {
type: String,
required: true
},
created_at: {
type: Date,
default: Date.now
}
}
]
});
module.exports = Board = mongoose.model('board', BoardSchema);
The error is pretty explicit, one of your comments in the comments array doesn't have a property content which seem to be required based on your model.
So double check what you are sending to the server by debugging/logging the content of the req.body.
Related
I want to get the comment by ID that is an array of embedded schema object in feedback schema model, see the code below:
Feedback schema:
const FeedbackSchema = new Schema({
receiver: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
comments: [
{
text: { type: String, maxlength: 500 },
postedBy: { type: Schema.Types.ObjectId, ref: 'User' },
date: { type: Date, default: Date.now() },
},
],
createdAt: {
type: Date,
default: Date.now(),
},
});
module.exports = {
FeedbackSchema: mongoose.model('Feedback', FeedbackSchema),
};
Comment controller and route:
router.get('/comment/:feedback_id/:comment_id', userAuthorization, getComment);
exports.getComment = async (req, res) => {
const feedback = await FeedbackSchema.findById({
_id: req.params.feedback_id,
});
if (!feedback) return res.status(404).send('Feedback not found');
const comment = feedback.comments.find({ _id: req.params.comment_id }); //error is in this line
if (!comment) return res.status(404).send('Comment not found');
return res.json(comment);
}
How do I get the comment based on feedback_id and comment_id?
Try to use findOne:
exports.getComment = async (req, res) => {
const feedback = await FeedbackSchema.findOne({
_id: req.params.feedback_id,
comments._id: req.params.comment_id
});
if (!feedback) return res.status(404).send('Feedback not found');
return res.json(feedback.comments);
};
Also, make sure that you declare the Comment schema separately:
const CommentSchema = new Schema({
text: { type: String, maxlength: 500 },
postedBy: { type: Schema.Types.ObjectId, ref: 'User' },
date: { type: Date, default: Date.now() },
})
const FeedbackSchema = new Schema({
receiver: {
type: Schema.Types.ObjectId,
ref: 'User',
required: true,
},
comments: [CommentSchema],
createdAt: {
type: Date,
default: Date.now(),
},
});
I cannot fetch users data from Mongo when I use populate() method for posts of users.
router.get("/users", (req, res) => {
User.find()
.populate("posts")
.exec()
.then((users) => {
res.json({ users });
})
.catch((err) => console.log(err));
});
Mongo Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const { ObjectId } = mongoose.Schema.Types;
const Post = require("../models/Post");
const UserSchema = new Schema({
name: {
type: String,
required: true
},
username: {
type: String,
requied: true
},
userimg: {
type: String
},
followers: [
{
type: ObjectId,
ref: "User"
}
],
following: [
{
type: ObjectId,
ref: "User"
}
],
posts: [
{
type: ObjectId,
ref: "Post"
}
],
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("users", UserSchema);
When I remove .populate("posts") than I get 200 Success status and users data but without popoulation of referred posts from the posts collection.
So i'll be doing a little modification to your model file
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Post = require("../models/Post");
const UserSchema = new Schema({
name: {
type: String,
required: true
},
username: {
type: String,
requied: true
},
userimg: {
type: String
},
followers: [
{
type: Schema.Types.ObjectId,
ref: "User"
}
],
following: [
{
type: Schema.Types.ObjectId,
ref: "User"
}
],
posts: [
{
type: Schema.Types.ObjectId,
ref: "Post"
}
],
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model("User", UserSchema);
Can you change your exec() to execPopulate()
router.get("/users", (req, res) => {
User.find()
.populate("posts")
.execPopulate()
.then((users) => {
res.json({ users });
})
.catch((err) => console.log(err));
});
Thank you all for your help. I found the error:
ref: "posts" instead of ref: "Post"
ref: "users" instead of ref: "User"
THIS PROBLEM IS A LITTLE LONGER. SO I TYPED BOLD THE CRITICAL INFORMATIONS FOR YOU.
I develop a project like stackoverflow. I have 4 databases which are:
problems
users
solutions
comments
I referrenced these schemas each other. Here is the Schemas:
Problem Schema
const problemSchema = new mongoose.Schema({
title: {
type: String,
required: [true, 'You have to enter a title']
},
content: {
type: String,
required: [true, 'You have to enter a content']
},
createdAt: {
type: Date,
default: Date.now()
},
slug: {
type: String
},
solution: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Solution'
},
],
comment: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
],
votes: {
type: Number,
default: 0
},
views: {
type: Number,
default: 0
},
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
})
module.exports = mongoose.model('Problem', problemSchema)
User Schema:
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: [true, 'You have to enter an email'],
unique: true,
match: [
/^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/,
'Please provide a valid email address.'
]
},
password: {
type: String,
required: [true, 'You have to enter a password'],
minlength: [6, 'Your password cannot be less than 6 character.'],
select: false
},
role: {
type: String,
default: 'user',
enum: ['user', 'admin']
},
createdAt: {
type: Date,
default: Date.now()
},
about: {
type: String
},
place: {
type: String
},
age: {
type: Number
},
blocked: {
type: Boolean,
default: false
},
problem: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Problem'
},
],
solution: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Solution'
}
],
comment: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
]
})
and Comments Schema:
const commentSchema = new mongoose.Schema({
content: {
type: String,
required: [true, 'You have to enter a content']
},
createdAt: {
type: Date,
default: Date.now()
},
isFunctional: {
type: Boolean,
default: false
},
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
problem: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Problem'
},
})
module.exports = mongoose.model('Comment', commentSchema)
In my project, I send problems into MongoDB. Then I send comment. After save comments, I add these comments into problems and user DB with a function.
function that comments are saved in DB:
const Comment = require('../models/comment/Comment')
const Problem = require('../models/problem/Problem')
const User = require('../models/user/User')
const asyncErrorWrapper = require('express-async-handler')
const addCommentToProblem = asyncErrorWrapper(async (req, res, next) => {
const {content, problemId} = req.body
const newComment = await Comment.create({
content: content,
problem: problemId,
user: req.user.id,
})
const problemOfComment = await Problem.findByIdAndUpdate(problemId, {
$push: { comment: newComment._id }
})
const userOfComment = await User.findByIdAndUpdate(req.user.id, {
$push: { comment: newComment._id }
})
})
Okey everything is so far so good. The problem comes here. When I try to get a problem, I populate some fields for example user fields. So I can add user information in this detail of problem. When populate user and comment in problem schema, it sends me the data. Still, we're ok. But when I try to get user field in comments, it doesn't populate user. It turns just objectId of user information.
Here is the function that I get problem:
const getAProblem = asyncErrorWrapper(async (req, res, next) => {
const {id} = req.params
const problems = null
await Problem.findByIdAndUpdate(id, {
$inc: { views: 1 }
}, { new: true })
.populate('user') ==> THIS LINE WORKS
.populate('comment') ==> THIS LINE WORKS
.populate('comment.user') ==> THIS LINE DOES NOT WORK
.exec(function(err, post) {
if(err) {
console.log(err)
}
res
.status(200)
.json({
success: true,
data: post
})
});
})
Thanks for reading and your patience. Any help will be appreciated.
See doc at https://mongoosejs.com/docs/populate.html
And try this way.
const getAProblem = asyncErrorWrapper(async (req, res, next) => {
const {id} = req.params
const problems = null
await Problem.findByIdAndUpdate(id, {
$inc: { views: 1 }
}, { new: true })
.populate('user') ==> THIS LINE WORKS
.populate({
'path': 'comment',
'populate': {
'path':'user'
}
})
.exec(function(err, post) {
if(err) {
console.log(err)
}
res
.status(200)
.json({
success: true,
data: post
})
});
})
I am getting error on console that : Cannot read property 'likes' of null
I am using postman for getting requests and putting response and response.
The array 'likes' is empty and here I am trying to insert the user id inside it but unable to insert it through unshift() method.
This is schema defined in a file Posts.js
const { text } = require('express');
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PostSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'users'
},
text: {
type: String,
required: true
},
name: {
type: String
},
avatar: {
type: String
},
likes: [
{
users: {
type: Schema.Types.ObjectId,
ref: 'users'
}
}
],
comment: [
{
users: {
type: Schema.Types.ObjectId,
ref: 'users'
},
text: {
type: String,
required: true
},
name: {
type: String,
},
avatar: {
type: String
},
date: {
type: Date,
default: Date.now
}
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Post = mongoose.model('post', PostSchema);
This is a express code for put request in file posts.js
const express = require('express');
const router = express.Router();
const { check, validationResult } = require('express-validator/check');
const auth = require('../../middleware/auth');
const Posts = require('../../models/Posts');
const User = require('../../models/User');
const { route } = require('./profile');
router.put('/like/:id', auth, async(req, res) => {
try {
const post = await Post.findById(req.params.id);
// Check if the post has already been liked
if(post.likes.filter(like => like.user.toString() === req.user.id).length > 0) {
return res.status(400).json({ msg: 'Post already liked' });
}
post.likes.unshift({ user: req.user.id });
await post.save();
res.json(post.likes);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
Here is the typo error I made. In the schema Posts.js in likes and comment array I wrote users instead of user.
const PostSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'users'
},
text: {
type: String,
required: true
},
name: {
type: String
},
avatar: {
type: String
},
likes: [
{
users: { // Here it has to be user
type: Schema.Types.ObjectId,
ref: 'users'
}
}
],
comment: [
{
users: { //Here it has to be user
type: Schema.Types.ObjectId,
ref: 'users'
},
This is My Playlist Schema:
when i fetch the comments for particular playlist i got only ids for the comments. How can i send all detail of comments of particular playlist to the front end?
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// const Video = require('./Video');
const User = require('./User');
const Comment = require('./Comment');
const VideoSchema = new Schema(
{
url: {
type: String
// required: true
},
shortDescription: {
type: String,
max: 120
// required: true
},
description: {
type: String,
min: 20,
max: 200
},
// createdOn: {
// type: Date,
// default: Date.now
// },
createdBy: { type: Schema.Types.ObjectId, ref: 'User' },
uploadedBy: { type: Schema.Types.ObjectId, ref: 'User' }
// uploadedOn: {
// type: Date,
// default: Date.now
// }
},
{
timestamps: true
}
);
const PlaylistSchema = new Schema(
{
name: {
type: String,
required: true
},
detail: {
type: String,
max: 100
},
tag: [ { type: String } ],
// user: {
// type: mongoose.Schema.Types.ObjectId,
// ref: 'User'
// },
uploadBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
videos: [ VideoSchema ],
// videos: [ { type: String } ],
// createdOn: { type: Date, default: Date.now },
updateBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
// updateOn: { type: Date, default: Date.now },
comments: [ { type: mongoose.Schema.Types.ObjectId, ref: 'Comment' } ]
},
{
timestamps: true
}
);
module.exports = Playlist = mongoose.model('Playlist', PlaylistSchema);
This is my Comment Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const User = require('./User');
const CommentSchema = new Schema(
{
createdBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
detail: {
type: String,
max: 200
},
// createdOn: {
// type: Date,
// default: Date.now
// },
// updatedOn: {
// type: Date,
// default: Date.now
// },
updatedBy: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
},
{
timestamps: true
}
);
CommentSchema.pre('remove', async function(next) {
try {
let foundUser = await User.findById(this.createdBy);
foundUser.comments.remove(this.id);
await User.save();
return next();
} catch (error) {
return next(error);
}
});
module.exports = Comment = mongoose.model('Comment', CommentSchema);
This is the function which will run when i fetch for comments
exports.getComments = async function(req, res, next) {
try {
console.log('request came for fetching comment');
let foundPlaylist = await Playlist.findById(req.params.playlist_id).populate('comments');
console.log('foundPlaylist:', foundPlaylist);
let foundComments = foundPlaylist.comments.map(async (comment) => {
return await Comment.findById(comment._id).populate('createdBy', { firstName: true });
});
return res.status(200).json(comments);
} catch (error) {
return next(error);
}
};
when i fetch the comments for particular playlist i got only ids for
the comments. How can i send all detail of comments of particular
playlist to the front end?
//Routes
router.route('/').get(getComments);
//index route
app.use('/api/users/:id/playlists/:playlist_id/comments', loginRequired, ensureCorrectUser, commentAuthRoute);
The comments field was defined to only contain a dbref:
comments: [ { type: mongoose.Schema.Types.ObjectId, ref: 'Comment' } ]
To retrieve the matching comment documents, use populate