Populate nested array with Mongoose - node.js

I have a user schema as shown below and I'm trying to populate the live projects array but I can't figure out how to access it.
const userSchema = new Schema({
local: {
email: String,
username: String,
password: String,
liveProjects: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'liveProject'
}]
},
google: {
googleId: String,
email: String,
username: String,
liveProjects: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'liveProject'
}]
}
});
const User = mongoose.model('user', userSchema);
module.exports = User;
If it wasn't embedded I could just use
User.findById(id).populate('liveProjects').exec((err,projects)=>{});
But how do I get access to 'local.liveProjects' or 'google.liveProjects' so that I can populate them?

Turns out it is just as simple as
User.findById(id).populate('local.liveProjects').exec((err,projects)=>{});

User Schema Here
`let UserSchema = new Schema({
email: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
},
profile: {
firstName: {type: String,required: true},
lastName: {type: String,required: true},
address1: {type: String},
address2: {type: String},
city: {type: String},
state: {type: String},
zip: {type: String},
phone: {type: String,required: true},
avatar:{ type: Schema.Types.ObjectId, ref: 'Avatar'},
shippingAddress:{
address1: {type: String},
address2: {type: String},
city: {type: String},
state: {type: String},
zip: {type: String}
},
},
redemptionCards : [{ type: Schema.Types.ObjectId, ref: 'CardCodes' }]
});`
Logic to get RedemptionCards:-
User.findOne({ email }).populate("redemptionCards")
.exec(function (err, user) {
CardData.populate(user.redemptionCards, {path: 'redemptionCards',match: { _id: { $ne: null }}}, function (err, cards) {
console.log(cards);
});
FYI - CardData is the Hardcoded JSON file. Hope this helps.

Related

Mongoose populate followers same document

I need to populate ObjectId parameters from the same Schema of users What am trying to do is I have 'Users' document and each record has followers and the ref is the same schema of users.
var userSchema = new Schema({
username: {type: String, unique: true, trim: true},
password: {type: String},
email: {type: String, trim: true},
avatar: {type: String},
fullname: {type: String},
bio: {type: String},
phone: {type: Number},
country: {type: String},
postal: {type: Number},
followers: [{ type: Schema.ObjectId, ref: 'User' }],
followed: [{ type: Schema.ObjectId, ref: 'User' }],
registered: {type: Date, default: Date.now}
});
var User = mongoose.model('users',userSchema);
Now when I tried to print the user information followers array return with ObjectId not the whole information
I try to print with this snippet
User.find().exec(function(error, groups) {
return res.status(200).send(groups);
});
What you want to achieve here is
User.find({})
.populate('followers')
.populate('followed')
.then(users => {
})
This will populate with both the followers and followed with their respective user objects

reddit comment system how to replicate in mongodb/nodejs

How do I make nested comment replies in MongoDB/mongoose to create a comment system like in reddit nesting. Here are my schemas i created so far:
var CommentSchema = Schema({
body: {type: String},
chapterId: {type: RK, ref: 'Chapter'},
by: {type: RK, ref: 'User'},
}, {timestamps: true});
var UserSchema = new Schema({
name: String,
username: {type:String, unique: true},
profile_pic: String,
password: String,
role:{type: [{
type: String,
enum: ['user', 'admin']
}],
default: ['user']
}
});

How to take only articles by given user Express.js

I want to display in my user/myarticlesview only articles by logged in user.
How can i do that:
Here is my User model and Article schema:
let userSchema = mongoose.Schema(
{
email: {type: String, required: true, unique: true},
passwordHash: {type: String, required: true},
salt: {type: String, required: true},
articles: [{type: ObjectId, ref: 'Article'}],
roles: [{type: ObjectId, ref: 'Role'}]
}
);
let articleSchema = mongoose.Schema (
{
author: {type: ObjectId, ref: 'User'},
title: {type: String, required: true },
content: {type: String, required: true },
phone: {type: Number, required: true },
date: {type: Date, default: Date.now() }
}
);
I want to do this in my userController and passed it to the view:
myArticlesGet: (req, res) => {
if (!req.isAuthenticated()) {
res.redirect('/');
return;
}
res.render('user/myarticles')
}
I cant figure it out how to make the query.Thank you.
As you are using express sessions you can store userId in the express session when the user is authenticated and then you can get user articles from user like that
User.find({_id: req.session.userId}).populate('articles')

Schema Association in Mongoose

I have 2 models:
Here is the User Model:
const userSchema = new mongoose.Schema({
email: { type: String, unique: true, required: true },
password: { type: String, required: true },
passwordResetToken: String,
passwordResetExpires: Date,
facebook: String,
twitter: String,
tokens: Array,
profile: {
name: String,
gender: String,
location: String,
website: String,
picture: String
}
}, { timestamps: true });
And here is the Revive Model:
const reviveSchema = new mongoose.Schema({
reviveShowName: {type: String, required: true},
reviveTitle: {type: String, required: true},
reviveCategory: {type: String, required: true},
reviveGoal: {type: Number, required: true},
revivePhoto: {type: String, required: true},
reviveVideo: {type: String},
reviveStory: {type: String},
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
name: String
}
}, { timestamps: true });
In the Revive model, I'm trying to the reference the author and get the author's id and that works... How do I also get the name from profiles -> name...? Clearly name: String is wrong...
Mongoose relations work, based on the ref and type value of the nested object. In your case you have associated the id property of author to point to the User model.
If you want to populate the author with the user information, you should just do :
author: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
Then in your query you just use populate
Revive.find({})
.populate( 'author' )
.exec( function( error, docs ) {
console.log( docs ); // will have `[{author:{profile:{...}}}]` data
} );

about mongoose populate relation a string field

I have two Schema
1 - User
UserSchema = new db.Schema({
email: {type: String, required: true},
pass: {type: String, required: true},
nick: {type: String, required: true},
admin: {type: String, default: ''},
reg: {type: Date, default: Date.now}
});
2 - Article
ArticleSchema = new db.Schema({
title: {type: String, required: true},
alise: {type: String},
time: {type: Date, defaults: Date.now},
view: {type: Number, defaults: 0},
author: {type: String},
content: {type: String},
classes: {type: db.Schema.Types.ObjectId, ref: 'Classes'},
user: {type: String, ref: 'User'}
});
I want ArticleSchema user field relation UserSchema nick.
my code:
Model.findOne({}).populate('classes user').exec(function(err, res){
if(err){
cb(err);
}else{
cb(null, res);
}
});
This is not working
message: 'Cast to ObjectId failed for value "tudou" at path "_id"'
What should I do?
Apparently you are using Mongoose, right?
If yes, to do it you must use db.Schema.Types.ObjectId in the ArticleSchema user field. So, your ArticleSchema should looks like this:
ArticleSchema = new db.Schema({
title: {type: String, required: true},
alise: {type: String},
time: {type: Date, defaults: Date.now},
view: {type: Number, defaults: 0},
author: {type: String},
content: {type: String},
classes: {type: db.Schema.Types.ObjectId, ref: 'Classes'},
user: {type: db.Schema.Types.ObjectId, ref: 'User'}
});
According to documentation:
There are no joins in MongoDB but sometimes we still want references to documents in other collections. This is where population comes in.
So, taking a look here, we can do something like that:
//To create one user, one article and set the user whos created the article.
var user = new UserSchema({
email : 'asdf#gmail.com',
nick : 'danilo'
...
});
user.save(function(error) {
var article = new ArticleSchema({
title : 'title',
alise : 'asdf',
user : user,
...
});
article.save(function(error) {
if(error) {
console.log(error);
}
});
}
And to find an article that was created for danilo:
ArticleSchema
.find(...)
.populate({
path: 'user',
match: { nick: 'danilo'},
select: 'email nick -_id'
})
.exec()
I suggest you to read about mongoose populate here
As of 4.5.0 You can use populate virtuals : http://mongoosejs.com/docs/populate.html#populate-virtuals
UserSchema = new db.Schema({
email: {type: String, required: true},
pass: {type: String, required: true},
nick: {type: String, required: true},
admin: {type: String, default: ''},
reg: {type: Date, default: Date.now}
});
ArticleSchema = new db.Schema({
title: {type: String, required: true},
alise: {type: String},
time: {type: Date, defaults: Date.now},
view: {type: Number, defaults: 0},
author: {type: String},
content: {type: String},
classes: {type: db.Schema.Types.ObjectId, ref: 'Classes'},
user: {type: String}
});
ArticleSchema.virtual('_user', {
ref: 'User', // The model to use
localField: 'user', // Find people where `localField`
foreignField: 'email', // is equal to `foreignField`
// If `justOne` is true, 'members' will be a single doc as opposed to
// an array. `justOne` is false by default.
justOne: true,
options: { sort: { name: -1 }, limit: 5 }
});
var User = mongoose.model('User', UserSchema);
var Article = mongoose.model('Article', ArticleSchema);
Article.find({}).populate('_user').exec(function(error, articles) {
/* `articles._user` is now an array of instances of `User` */
});

Resources