Load post from Followers in Nodejs and Mongoose - node.js

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

Related

How to get comment from embedded document in mongodb?

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(),
},
});

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?

Is that possible, to solve a complex mongoose populate query?

I have four tables.
#First table
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
#First table
var studentSchema=new Schema({
student_name: { type: String, required: true },
sendKey: { type: String },
created_by: { type:String },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('Student',studentSchema);
#Second table
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var institutionSchema=new Schema({
institution_name: { type: String, lowercase: true },
email: { type:String },
created_by: { type:String },
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('Institution',institutionSchema);
#third table
var mongoose=require('mongoose');
// var Institution = ('./institution');
var Schema=mongoose.Schema;
var batchSchema=new Schema({
batch_name: { type: String, required: true },
institution: { type: Schema.Types.ObjectId, ref: 'Institution' },
created_by: { type:String },
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('Batch',batchSchema);
#Fourth Table
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var batchtudentSchema=new Schema({
student_id: { type: Schema.Types.ObjectId, ref: 'Student', required : true},
batch_id: { type: Schema.Types.ObjectId, ref: 'Batch', required:true},
created_at: { type: Date, default: Date.now },
updated_at: { type: Date, default: Date.now },
})
module.exports=mongoose.model('BatchStudent',batchtudentSchema);
I have an institution Id. I want to find all students of this institution with Batch details.
Primarily I have tried to.. do that.
Student.find().populate('BatchStudent').pupulate('Batch').populate('Institution').exec((err, docs) => {
console.log(docs)
res.json(
{
data:docs
}
)
})
It is not working.. sending just all student data.. How can I get the data correctlly?
// Student Schema
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var studentSchema=new Schema({
student_name: {
type: String,
required: true
},
sendKey: {
type: String
},
batchStudent: {
type: Schema.Types.ObjectId,
ref: 'BatchStudent',
}
created_by: {
type:String
},
updated_at: {
type: Date,
default: Date.now
},
})
module.exports=mongoose.model('Student',studentSchema);
// BatchStudent Schema
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var batchtudentSchema=new Schema({
student_id: {
type: Schema.Types.ObjectId,
ref: 'Student',
required : true
},
batch_id: {
type: Schema.Types.ObjectId,
ref: 'Batch'
},
institution: {
type: Schema.Types.ObjectId,
ref: 'Institution'
}
})
module.exports=mongoose.model('BatchStudent',batchtudentSchema);
// Institution Schema
var mongoose=require('mongoose');
var Schema=mongoose.Schema;
var institutionSchema=new Schema({
institution_name: {
type: String,
lowercase: true
},
email: {
type: String
},
created_by: {
type:String
}
});
module.exports=mongoose.model('Institution',institutionSchema);
If the I removed created_at and updated_at to avoid duplication. Obey DRY principles always (Don't repeat yourself)
If you need to get the document you can simply use Deep Population/Association for that as shown below:
Student.find({}).populate({
path : 'batchStudent',
populate : {
path : 'institution'
}
}).exec(function (err, res) {
// do whatever you need to do here
})

When i fetch comments for particular Playlist i am getting all comments. And How can i get the other properties of comments?

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

Mongoose(mongoDB) Linking multiple schema's

Im relatively new to MongoDB and Mongoose. Im much used to MySQL so in used to inner joining tables on calls. Ive read a lot that you can link two Mongoose Schemas to achieve the same outcome. How would like like the two schemas together to when I make a call to get a chore by id it'll return the chore and then for the assignedTo & createdBy have the user scheme data for the said userId?
Chore Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ChoreSchema = new Schema({
title: {
type: String,
required: true
},
desc: {
type: String,
required: true
},
time: {
type: Number,
required: true
},
reaccurance: {
type: [{
type: String,
enum: ['Daily', 'Weekly', 'Bi-Weekly', 'Monthly']
}]
},
reward: {
type: Number,
required: true
},
retryDeduction: {
type: Number,
required: false
},
createdDate: {
type: Date,
default: Date.now
},
createdBy: {
type: String,
required: true
},
dueDate: {
type: Date,
required: true
},
status: {
type: [{
type: String,
enum: ['new', 'pending', 'rejected', 'completed', 'pastDue']
}],
default: ['new']
},
retryCount: {
type: Number,
default: 0,
required: false
},
rejectedReason: {
type: String,
required: false
},
familyId: {
type: String,
required: true
},
assignedTo: {
type: String,
required: false,
default: ""
}
});
let Chores = module.exports = mongoose.model('Chores', ChoreSchema);
module.exports.get = function (callback, limit) {
Chores.find(callback).limit(limit);
};
User Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
role: {
type: [{
type: String,
enum: ['Adult', 'Child']
}]
},
birthday: {
type: String,
required: false
},
familyId: {
type: String,
required: true
},
balance: {
type: Number,
required: true,
default: 0.00
}
});
let Users = module.exports = mongoose.model('Users', UserSchema);
module.exports.get = function (callback, limit) {
Users.find(callback).limit(limit);
};
Im trying to link ChoreSchema.createdBy & ChoreScheme.assignedTo by UserSchema._id
How I make the call in Node.js:
exports.index = function(req, res) {
Chore.get(function(err, chore) {
if (err)
res.send(err);
res.json({
message: 'Chore List',
data: chore
});
});
};
Mongoose has a more powerful alternative called populate(),
which lets you reference documents in other collections.
https://mongoosejs.com/docs/populate.html
Here is how you can link ChoreSchema.createdBy and ChoreScheme.assignedTo by UserSchema._id
var mongoose = require('mongoose');
const { Schema, Types } = mongoose;
var UserSchema = new Schema({
firstName: { type: String, required: true },
...
})
var ChoreSchema = new Schema({
title: { type: String, required: true },
...
//The ref option is what tells Mongoose which model to use during population
assignedTo: { type: Types.ObjectId, ref: 'Users' },
createdBy: { type: Types.ObjectId, ref: 'Users' },
})
let Chores = mongoose.model('Chores', ChoreSchema);
let Users = mongoose.model('Users', UserSchema);
Then in your express route handler you can populate assignedTo & createdBy like this
router.get('/chores/:id', function (req, res) {
const choreId = req.params.id;
Chores.find({ _id: choreId })
.populate('createdBy') // populate createdBy
.populate('assignedTo') // populate assignedTo
.exec(function (err, chore) {
if(err) {
return res.send(err)
}
res.json({ message: 'Chore List', data: chore });
});
})

Resources