MongoDB: How to get data by join - node.js

I am having following two schemas in mongodb
var userSchema = new Schema({
first_name: String,
last_name: String,
email: String
});
var messageSchema = new Schema({
sender: {type: Schema.Types.ObjectId, ref: 'users' },
receiver: {type: Schema.Types.ObjectId, ref: 'users' },
message: String,
sentOn: Date,
});
var Users = mongoose.model('users', userSchema);
var Messages = mongoose.model('messages', messageSchema);
How can I query to get the all users from 'users' collection and their last message (single) from 'messages' collection?

Related

How to access and populate a referenced object schema in a larger document (MERN)

Making an app with a variety of schemas, many having other objects (Schema.Types.ObjectIds) as their properties.
When doing this, I can access the sub-object's property, as long as that sub-object's property is a string. But I'm having issues with it if that sub-object's property is yet another object (and then I need to query properties from that, string or not). For example, the first works fine:
user schema-> friends property of user (which is a list of user objects) -> username property of friend (which is a string)
But this I'm having issues with, I'm getting a string id and not the actual object**:
user schema-> profilePosts property of user (which is a list of profilePost objects) -> author property of profilePost (which is a user object)** -> author username property of profilePost (which is a string)
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: {type: String, required: true},
password: {type: String, required: true},
friends: [{type: Schema.Types.ObjectId, ref: "User"}],
profilePosts: [{type: Schema.Types.ObjectId, ref: "ProfilePost"}],
friendRequests: [{type: Schema.Types.ObjectId, ref: "User"}],
})
module.exports = mongoose.model('User', UserSchema);
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var ProfilePostSchema = new Schema({
date: {type: Date, required: true},
author: {type: Schema.Types.ObjectId, ref: "User"},
content: {type: String, required: true},
comments: [{type: Schema.Types.ObjectId, ref: "ProfilePostComment"}],
likes: [{type: Schema.Types.ObjectId, ref: "User"}],
hostProfile: {type: Schema.Types.ObjectId, required: true,ref: "User"},
})
module.exports = mongoose.model('ProfilePost', ProfilePostSchema);
exports.user_friends_render = async (req,res) => {
try {
const ViewedProfile = await User.find({}, 'username friends profilePosts friendRequests').populate('friends').populate('profilePosts').populate('friendRequests');
res.status(200).json(ViewedProfile);
} catch(error) {
res.status(200).json({message: error.message});
}
}
objects are string ids instead of objects
Mongoonse populate root object but not implicit deep populate
You can replace string by object as argument at populate method,
for provide full path to populate
const ViewedProfile = await User
.find({}, 'username friends profilePosts friendRequests')
.populate('friends')
.populate({
path: "profilePosts",
populate: [
{
path: "author",
// model: UserModel
},
{
path: "comments",
// model: ProfilePostCommentModel
},
{
path: "likes",
// model: UserModel
},
{
path: "hostProfile",
// model: UserModel
}
]
})
.populate('friendRequests');
You can see fully post at this problem.

Mongoose Nested Populate Not Working

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

Assign _id or Object to mongoose.Schema.Types.ObjectId

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

One to Many relationship in Express Models using mongoDB

This is doctors.js model:
var mongoose = require('mongoose'), Schema = mongoose.Schema;
var Patient = require('./patient.js');
var doctorSchema = mongoose.Schema({
firstName: String,
lastName: String,
qualifications: String,
photo: Buffer,
_patients: [{ type: Schema.Types.ObjectId, ref: 'Patient' }]
});
var Doctor = mongoose.model('Doctor', doctorSchema);
module.exports = Doctor;
This is patients.js model:
var mongoose = require('mongoose');
var Doctor = require('./doctor.js');
var patientSchema = mongoose.Schema({
firstName: String,
lastName: String,
dob: String,
gender: String,
primaryDiagnosis: String,
duration: String,
_doctorIncharge: {type: Number, ref: 'Doctor'},
hospitalNumber: String,
photo: Buffer
});
var Patient = mongoose.model('Patient', patientSchema);
module.exports = Patient;
Is this the way to make a one to many relationship work?

How to reference another schema in my Mongoose schema?

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

Resources