500 Error when using method populate in Express and Mongo - node.js

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"

Related

Mongo populate not working and not retrieve data model

I have a problem in populate method in mongodb it can't retrieve data from model. Can anyone help me solve that problem?
This is the code
router.get('/', auth, async (req, res) => {
try {
const user = req.user._id;
const wishlist = await Wishlist.find({ user, isLiked: true })
.populate({
path: 'Products',
select: 'title',
})
.sort('-updated');
res.status(200).json({
wishlist,
});
} catch (error) {
res.status(400).json({
error: 'Your request could not be processed. Please try again.',
});
}
});
When I navigate to http://localhost:3000/wishlist/, this is the response I get:
{
"wishlist": [
{
"product": "60cb5eb82cc7091ae2e31c88",
"user": "60cb6c46291247466fe08f92",
"isLiked": true,
"_id": "60d1a656567e08bf89571209",
"updated": "2021-06-22T10:09:25.295Z",
"created": "2021-06-22T08:59:02.434Z",
"__v": 0
}
]
}
The model of products
const mongoose = require('mongoose');
const { Schema } = mongoose;
const ProductSchema = mongoose.Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
category:{
type: Schema.Types.ObjectId,
ref: 'Categories',
default: null
},
photo: { type: String, required: true },
createdAt: {
type: Date,
default: new Date(),
},
updateAt: Date,
price: {
type: String,
required: true,
},
quantity: {
type: Number
}
,
isActive: {
type: Boolean,
default: true
},
user: {
type: Schema.Types.ObjectId,
ref: "User",
}
});
module.exports = mongoose.model('Product', ProductSchema);
The model for wishlist:
const Mongoose = require('mongoose');
const { Schema } = Mongoose;
// Wishlist Schema
const WishlistSchema = new Schema({
product: {
type: Schema.Types.ObjectId,
ref: 'Product',
default: null,
},
user: {
type: Schema.Types.ObjectId,
ref: 'User',
default: null,
},
isLiked: {
type: Boolean,
},
updated: {
type: Date,
default: Date.now,
},
created: {
type: Date,
default: Date.now,
},
});
module.exports = Mongoose.model('Wishlist', WishlistSchema);
Can anyone help me please to find the solution for that problem?

I am getting this error: Cannot read property 'likes' of null

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'
},

mongoose.populate() returning an empty array

I know, this is one of the popular questions out there. On populate I expect it to return the user with his posts, but it's returning an empty array of posts.
Here is my User model.
User.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const userSchema = new Schema({
username: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
posts: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Post"
}]
}, { timestamps: true })
const User = mongoose.model("User", userSchema)
module.exports = User
Post.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const postSchema = new Schema({
postTitle: { type: String, required: true },
postDescription: { type: String, required: true },
user: { type: Schema.Types.ObjectId, ref: "User" },
}, { timestamps: true }
)
const Post = mongoose.model("Post", postSchema)
module.exports = Post
router.get("/posts/:id", usersController.getUserPosts)
usersController.js
getUserPosts: (req, res) => {
User.findById(req.params.id).populate("posts").exec((err, posts) => {
if (err) console.log(err)
console.log(posts)
})
}
I'm getting this:
{ posts: [],
_id: 5e4e3e7eecd9a53c185117d4,
username: 'rick',
email: 'rick#gmail.com',
createdAt: 2020-02-20T08:08:30.878Z,
updatedAt: 2020-02-20T08:08:30.878Z,
__v: 0 }
Where am I going wrong?

How to make a comment on board in Nodejs

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.

Load post from Followers in Nodejs and Mongoose

I have a schema for post like below, but am having problem fetching post from my followers. i have also tried using but all to no avail. please help
I have a schema for post like below, but am having problem fetching post from my followers. i have also tried using but all to no avail. please help
I have a schema for post like below, but am having problem fetching post from my followers. i have also tried using but all to no avail. please help
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:[
{
user:{
type: Schema.Types.ObjectId,
ref: 'users'
}
}
],
comments:[
{
user:{
type: Schema.Types.ObjectId,
ref: 'users'
},
text:{
type:String,
required: true
},
name: {
type: String
},
avatar: {
type: String
},
date:{
type:Date,
default: Date.now
},
likes: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'users'
}
}
],
}
],
reposter: [
{
user: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
date: {
type: Date,
default: Date.now
}
}
],
numberOfRepost: { type: Number, default: 0 },
date: {
type: Date,
default: Date.now
}
});
module.exports = Post = mongoose.model('post', PostSchema);
First of all, you should rethink about mongo-collection design, Here is some tip which it is better to consider.
Use Upper Camel case for declaring mongoose model objects. ( Post, User, ... )
Always put _ before any reference variable. ( _user in Post models )
Separate your collections and avoid redundant properties as much as possible.
Always use Plural of a name for collections. ( posts vs post )
Do not forget to add created and updated property to each collection. ( this hack helps you for logging and investigating your models )
Now, let's look at our new design:
name and avatar are redundant data in the Post model. you can populate them later.
Separate Like, Comment, RePoster from Post model.
Here is the refined Post model object.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PostSchema = new Schema(
{
_user: { type: Schema.Types.ObjectId, ref: 'User' },
text:{ type:String, required: true },
rePostsNum: { type: Number, default: 0 },
// any other meta data which you need
creaetd: Date,
updated: Date
},
{
collection: 'posts',
strict: true,
autoIndex: true
}
);
PostSchema.pre('save', function (next) {
if( this.isNew )
this.created = new Date();
this.updated = new Date();
next();
});
module.exports = Post = mongoose.model('Post', PostSchema);
You can also put _comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }] into the Post model, but think about it! If it is possible to store thousands of comments reference key in _comments array, it is not recommended, it's like technical debt.
Other models:
Comment:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CommentSchema = new Schema(
{
_user: { type: Schema.Types.ObjectId, ref: 'User' },
_post: { type: Schema.Types.ObjectId, ref: 'Post' },
text:{ type:String, required: true },
likesNum: { type: Number, default: 0 },
creaetd: Date,
updated: Date
},
{
collection: 'posts',
strict: true,
autoIndex: true
}
);
CommentSchema.pre('save', function (next) {
if( this.isNew )
this.created = new Date();
this.updated = new Date();
next();
});
module.exports = Comment = mongoose.model('Comment', CommentSchema);
LikePost
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const LikePostSchema = new Schema(
{
_user: { type: Schema.Types.ObjectId, ref: 'User' },
_post: { type: Schema.Types.ObjectId, ref: 'Post' },
creaetd: Date,
updated: Date
},
{
collection: 'likePosts',
strict: true,
autoIndex: true
}
);
LikePostSchema.pre('save', function (next) {
if( this.isNew )
this.created = new Date();
this.updated = new Date();
next();
});
module.exports = LikePost = mongoose.model('LikePost', LikePostSchema);
LikeComment
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const LikeCommentSchema = new Schema(
{
_user: { type: Schema.Types.ObjectId, ref: 'User' },
_comment: { type: Schema.Types.ObjectId, ref: 'Comment' },
creaetd: Date,
updated: Date
},
{
collection: 'likeComments',
strict: true,
autoIndex: true
}
);
LikeCommentSchema.pre('save', function (next) {
if( this.isNew )
this.created = new Date();
this.updated = new Date();
next();
});
module.exports = LikeComment = mongoose.model('LikeComment', LikeCommentSchema);
User
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema(
{
name:{ type:String, required: true },
avatar:{ type:String, required: true },
// any other meta data which you need
creaetd: Date,
updated: Date
},
{
collection: 'users',
strict: true,
autoIndex: true
}
);
UserSchema.pre('save', function (next) {
if( this.isNew )
this.created = new Date();
this.updated = new Date();
next();
});
module.exports = User = mongoose.model('User', UserSchema);
RePost
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const RePostSchema = new Schema(
{
_user: { type: Schema.Types.ObjectId, ref: 'User' },
_post: { type: Schema.Types.ObjectId, ref: 'Post' },
creaetd: Date,
updated: Date
},
{
collection: 'rePosts',
strict: true,
autoIndex: true
}
);
RePostSchema.pre('save', function (next) {
if( this.isNew )
this.created = new Date();
this.updated = new Date();
next();
});
module.exports = RePost = mongoose.model('RePost', RePostSchema);
Welcome back!
Now our new design is fully scalable and guides you to clean and robust code.
Finally, we can query and populate data, Here is two cool sample code:
Load specific user's posts
var mongoose = require('mongoose');
var User = mongoose.model('User');
var Post = mongoose.model('Post');
var Comment = mongoose.model('Comment');
var LikePost = mongoose.model('LikePost');
var LikeComment = mongoose.model('LikeComment');
var RePost = mongoose.model('RePost');
Post
.find({ _user: userId })
.select('_id _user text ...')
.populate({
path: '_user',
select: '_id name avatar ...'
})
.exec(function (err, poats) {
Load specific post's comments
Comment
.find({ _post: postId })
.select('_id _post _user text ...')
.populate({
path: '_user',
select: '_id name avatar ...'
})
.exec(function (err, comments) {
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true,
},
username: {
type: String,
required: true
},
password: {
type: String,
required: true
},
avatar: {
type: String
},
phonenumber: {
type: String,
required: true
},
email: {
type: String
},
resetPasswordToken: {
type: String
},
lastlogin: {
type: Date, default: Date.now
},
passwordUpdated: {
type: Date, default: Date.now
},
resetPasswordExpires: {
type: Date
},
dateofbirth: {
type: Date
},
dateJoined: {
type: Date,
default: Date.now
},
sentRequest: [{
username: { type: String, default: '' },
date: {
type: Date,
default: Date.now
}
}],
request: [{
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
username: { type: String, default: '' },
name: { type: String, default: '' },
phone: { type: String, default: '' },
date: {
type: Date,
default: Date.now
}
}],
friendsList: [{
friendId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
friendName: { type: String, default: '' },
friendUsername: { type: String, default: '' },
friendPhone: { type: String, default: '' },
date: {
type: Date,
default: Date.now
}
}],
followers: [{
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
date: {
type: Date,
default: Date.now
}
}],
blockedContacts: [
{
userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },
date: {
type: Date,
default: Date.now
}
}],
totalRequest: { type: Number, default: 0 },
repost: [
{
postId: { type: mongoose.Schema.Types.ObjectId, ref: "Post" },
date: {
type: Date,
default: Date.now
}
}
],
accolades: [
{
user: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'
},
remarks: {
type: String
},
date: {
type: Date,
default: Date.now
}
}
],
followers: [{
user: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'
},
date: {
type: Date,
default: Date.now
}
}],
following: [{
user: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'
},
date: {
type: Date,
default: Date.now
}
}],
})
UserSchema.pre('save', function (next) {
var user = this;
//check if password is modified, else no need to do anything
if (!user.isModified('pass')) {
return next()
}
user.pass = bcrypt.hashSync(password, bcrypt.genSaltSync(8), null);
next()
})
module.exports = User = mongoose.model('Users', UserSchema);
This is the user schema

Resources