So I am currently extremely confused when it comes to mongoose populating.
My data structure is as follows: User has an array of Clients, a Client has an array of loans. I am using User.find and populating the client, no problem. But then how do I populate the loans that is inside of the client? I have tried this:
Basically, the goal is to pass in an array of Clients, each client will contain a loan. But for now, I want that loan object to be empty. The Client is being populated correctly, however, the Loan reference is being passed as undefined.
app.get("/loans", IsLoggedIn, function(req, res) {
User.findById(req.user._id).populate({path: "clients", populate: { path: "loans", model: "loan"}}).exec(function(err, user){
if(err){
console.log(err);
} else{
var amountRepaid = calcRepaid(user.clients.loans);
console.log(user.clients.loans);
res.render("index", {clients: user.clients, amountRepaid: amountRepaid});
}
});
However it doesn't seem to work, my models are listed below and any help is appreciated!
models:
Client:
var mongoose = require("mongoose");
var clientSchema = mongoose.Schema({
loans: [{
type: mongoose.Schema.Types.ObjectId,
ref: "loan"
}],
emailAdderess: String,
firstname: String,
lastname: String,
contactNumber: String ,
dateCreated: {type: Date, default: Date.now},
gender: String,
})
module.exports = mongoose.model("Client", clientSchema);
User:
const mongoose = require("mongoose");
const passportLocalMongoose = require("passport-local-mongoose");
var UserSchema = mongoose.Schema({
username: String,
password: String,
firstname: String,
lastname: String,
clients: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Client"
}]
});
UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);
Loan:
var mongoose = require("mongoose");
var LoanSchema = mongoose.Schema({
firstName: String,
lastName: String,
email: String,
contactNumber: Number,
amountBorrowed: Number,
length: String,
address: String,
dateDue: Date,
gender: String,
date: { type: Date, default: Date.now },
amountRepaid: { type: Number, default: 0},
loanRepaid: {type: Boolean, default: false}
})
module.exports = mongoose.model("loan", LoanSchema);
Try this:
.populate({
path: 'clients',
populate: {
path: 'clients.loans'
}
})
Related
Before everyone tells me I can't call a const before initializing, I do know that.
But I think this is the simplest way to render the concept I have in mind, (where any subdocument within the replies array also has the same schema as the parent, and documents within the replies array of those subdocuments also having the same schema). I would really appreciate anyone's input.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
var commentSchema = new mongoose.Schema({
content: String,
createdAt: {
type: Date,
default: Date.now
},
score: {
type: Number,
default: 1
},
username: {
type: String,
lowercase: true
},
parent: {
type: Schema.Types.ObjectId,
ref: 'comment'
},
replyingTo: String,
replies: [commentSchema]
});
module.exports = mongoose.model("comment", commentSchema);
Since a const can't be called before initialization, to fix this issue the parent schema should be called on the children array after initialization the code below:
commentSchema.add({ replies: [commentSchema] })
The final result should look like this:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const commentSchema = new mongoose.Schema({
content: String,
createdAt: {
type: Date,
default: Date.now
},
score: {
type: Number,
default: 1
},
username: {
type: String,
lowercase: true
},
parent: {
type: Schema.Types.ObjectId,
ref: 'comment'
},
replyingTo: String,
});
commentSchema.add({ replies: [commentSchema] })
I have followed the mongoose docs for populating related objects, everytime authSessions is empty. I can see in mongo sessions are being populated along with the related userId field. I have tried specifying ”path” and “model” options in the populate function as well but that didn’t work either. Anyone have any ideas?
//Session.js
const SessionSchema = new mongoose.Schema({
_id: Schema.Types.ObjectId,
sessionId: { type: String, index: true },
createdDate: { type: Date, default: Date.now },
revoked: Boolean,
revokedAt: Date,
userId: {type: Schema.Types.ObjectId, ref: 'User', index: true}
})
module.exports = mongoose.models.Session || mongoose.model('Session', SessionSchema);
//User.js
const UserSchema = new mongoose.Schema({
_id: Schema.Types.ObjectId,
username: { type: String, index: true },
email: { type: String, index: true },
password: String,
registrationDate: { type: Date, default: Date.now },
authSessions: [{type: Schema.Types.ObjectId, ref: 'Session'}]
})
module.exports = mongoose.models.User || mongoose.model('User', UserSchema);
const user = await User.findById(session.userId).populate('authSessions').exec();
console.log(user) //authSessions is empty
{
_id: new ObjectId("62b6ea393e042868caa68c7d"),
username: 'asdfasdfasdf',
email: 'testaskldjflk#djlkajdf.com',
password: 'testaskldjflk#djlkajdf.com',
authSessions: [], //empty here always
registrationDate: 2022-06-25T10:58:01.709Z,
__v: 0
} ```
MongoDB, and by extension mongoose, doesn't automatically create relations for you.
If you create a Session document, you need to explicitly add it to a User document if you want populate to work:
// create a new session document and save it
const userSession = new Session(…);
await userSession.save();
// !! update the user document and save it
user.authSessions.push(userSession);
await user.save();
I'm working on my personal project which is just simple blog and I got stuck with this problem:
I have 3 Mongoose Schemas:
Blog:
var blogSchema = new mongoose.Schema({
title: String,
image: String,
description: String,
body: String,
created: { type: Date, default: Date.now() },
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
Comment:
var commentSchema = new mongoose.Schema({
text: String,
author_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
});
User:
var userSchema = new mongoose.Schema({
username: String,
password: String,
avatar_url: String,
email: String
});
And in each blog post I'm trying to display comments from array which is working correctly but then I don't know how to access to User model to display usernames and avatar_urls
app.get("/blogs/:id",function(req,res){
Blog.findById(req.params.id).populate("comments").populate("author_id").exec(function(err,findBlog){
if(err){
res.redirect("back");
console.log(err);
}else{
res.render("show" , {blog: findBlog});
}
})
})
you have to declare user information like username in the blog schema then only you can send request to userschema for avatar_url
I have the schema which refers to another object.
model/message.js
var moogoose = require('mongoose');
var Schema = moogoose.Schema;
var schema = new Schema({
.
user: {type: Schema.Types.ObjectId, ref: 'User'}
.
});
module.exports = moogoose.model('Message', schema);
Suppose user is the object extracted from database.
Should I assign user._id or user object to user property of message model. I have tried both, they yield same result that is _id as value of user property.
var message = new Message({
user: user._id,
});
or:
var message = new Message({
user: user
});
Here is one of the schema that I use.
var mongoose=require('mongoose');
var config=require('./config'); //configuarations and APIS keys stored in this file
mongoose.connect(config.MONGO_URL, {server:{poolSize:10}});
var Schema = mongoose.Schema, ObjectId = Schema.ObjectId;
var users = new mongoose.Schema({
mobile: { type: String, unique: true },
hash: String,
location:{ type:[Number, Number], index:'2d'},
locName: String,
created_at: Number,
image: {type: String, default: 'NONE'},
role: {type: String, default: 'USER'},
name: {type: String, default: 'NONE'},
});
exports.users = mongoose.model('users', users);
var comments = new mongoose.Schema({
uid: { ObjectId, ref: 'users'},
liked_by: {type: [ObjectId], default: []},
like_count: {type: Number, default: 0},
created_at: Number
});
comments.index({spark_id:1, created_at:1});
exports.comments = mongoose.model('comments', comments);
This is one of the functions
dbase.comments.find({uid: req.body.user._id, function(err, response){
if(!err){
//do what you want
}else{
//handle error
}
}).sort({created_at: -1}).skip(count).limit(50).lean();
I'm building a Mongoose schema for a dating app.
I want each person document to contain a reference to all the events they've been to, where events is another schema with its own models in the system. How can I describe this in the schema?
var personSchema = mongoose.Schema({
firstname: String,
lastname: String,
email: String,
gender: {type: String, enum: ["Male", "Female"]}
dob: Date,
city: String,
interests: [interestsSchema],
eventsAttended: ???
});
You can do so by using Population
Population is the process of automatically replacing the specified
paths in the document with document(s) from other collection(s). We
may populate a single document, multiple documents, plain object,
multiple plain objects, or all objects returned from a query.
Suppose your Event Schema is defined as follows:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
var eventSchema = Schema({
title : String,
location : String,
startDate : Date,
endDate : Date
});
var personSchema = Schema({
firstname: String,
lastname: String,
email: String,
gender: {type: String, enum: ["Male", "Female"]}
dob: Date,
city: String,
interests: [interestsSchema],
eventsAttended: [{ type: Schema.Types.ObjectId, ref: 'Event' }]
});
var Event = mongoose.model('Event', eventSchema);
var Person = mongoose.model('Person', personSchema);
To show how populate is used, first create a person object,
aaron = new Person({firstname: 'Aaron'})
and an event object,
event1 = new Event({title: 'Hackathon', location: 'foo'}):
aaron.eventsAttended.push(event1);
aaron.save(callback);
Then, when you make your query, you can populate references like this:
Person
.findOne({ firstname: 'Aaron' })
.populate('eventsAttended') // only works if we pushed refs to person.eventsAttended
.exec(function(err, person) {
if (err) return handleError(err);
console.log(person);
});
To reference the ObjectId of one table in another table refer below code
const mongoose = require('mongoose'),
Schema=mongoose.Schema;
const otpSchema = new mongoose.Schema({
otpNumber:{
type: String,
required: true,
minlength: 6,
maxlength: 6
},
user:{
type: Schema.Types.ObjectId,
ref: 'User'
}
});
const Otp = mongoose.model('Otp',otpSchema);
// Joi Schema For Otp
function validateOtp(otp) {
const schema = Joi.object({
otpNumber: Joi.string().max(6).required(),
userId: Joi.objectId(), // to validate objectId we used 'joi-objectid' npm package
motive: Joi.string().required(),
isUsed: Joi.boolean().required(),
expiresAt: Joi.Date().required()
});
// async validate function for otp
return schema.validateAsync(otp);
}
exports.Otp = Otp;
exports.validateOtp = validateOtp;
List item
var personSchema = mongoose.Schema({
firstname: String,
lastname: String,
email: String,
gender: {
type: String,
enum: ["Male", "Female"]
}
dob: Date,
city: String,
interests: [interestsSchema],
eventsAttended[{
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Place"
}],
**//ref:"Places"...you have put the other model name**
*OR*
eventsAttended[{
type: mongoose.Types.ObjectId,
required: true,
ref: "Place"
}],
});