How to save data in mongodb express by referring another document - node.js

I have created the following User schema
const UserSchema = mongoose.Schema(
{
fullName: {
type: String,
required: true,
index: true,
},
department: {
type: mongoose.Schema.Types.ObjectId,
ref: "Department",
required: true,
},
},
});
and my Department schema looks like the following
const DepartmentSchema = mongoose.Schema(
{
name: {
type: String,
unique: true,
required: true,
},
description: {
desc: "Description.",
type: String,
},
},
{
strict: true,
versionKey: false,
timestamps: { createdAt: "createdAt", updatedAt: "updatedAt" },
});
Now I'm able to create departments and all is working well in Postman and also my Angular application. But while creating User it only saves the department ID that I've selected or added in my form. This is the data that I've tried to create
user = {
department: "5f806be7c9a3c02c7c61f9f1"
fullName: "John Joshua"
}
and my create route controller looks like this
exports.create = async (req, res) => {
const newUser = new User({
fullName: req.body.fullName,
department: req.body.department,
});
try {
const errors = validationResult(req); // I've used express validator here
if (!errors.isEmpty()) {
res.status(400).json({ errors: errors.array() });
return;
}
const savedUser = await newUser.save();
res.json(savedUser); // Here I was expecting to return the new saved user with Department details
} catch (err) {
res.status(500).json({ message: err });
}
};
So my response is all good and working well but department only contains the ID with nothing more.
How can I send a response data with Department details? Any help is appreciated.

Related

Moongoose populate method returning an empty array

I am trying to fetch the blogs that a user has posted using mongoose populate method but not able to do so but when I try to look for the user who posted a blog I am able to do so. Tell me what I am doing wrong.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
blogPosts: [{ type: mongoose.Types.ObjectId, ref: "Blogs", required: true }],
});
const Users = mongoose.model("Users", userSchema);
module.exports = Users;
This is my user model
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const blogSchema = new Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
image: {
type: String,
required: true,
},
user: {
type: mongoose.Types.ObjectId,
ref: "Users",
required: true,
},
});
const blogs = mongoose.model("Blogs", blogSchema);
module.exports = { blogs, blogSchema };
this is my blogs model
router.get("/users/:id", async (req, res) => {
let userBlogs;
try {
userBlogs = await users.find({ _id: req.params.id }).populate("blogPosts");
if (!userBlogs) {
return res.status(404).json({ msg: "No user found" });
}
return res.status(200).json(userBlogs);
} catch (err) {
return res.status(500).json({ err });
}
});
this is the route that I use for fetching all the blogs that a user has posted.This is just sending me back an empty posts array.
router.post("/newBlog/:id", async (req, res) => {
let blogAuthor;
try {
blogAuthor = await users.findOne({ _id: req.params.id });
} catch (err) {
return res.status(404).json({ message: "user not found" });
}
const newBlog = blogs({
title: req.body.title,
description: req.body.description,
image: req.body.imageUrl,
user: blogAuthor._id,
});
try {
await blogAuthor.blogPosts.push(newBlog);
await newBlog.save();
return res.status(200).json(blogAuthor.blogPosts);
} catch (err) {
return res.status(500).json(err);
}
});
the above is the route that I use to add new blog to the db.
router.get("/allBlogs", async (req, res) => {
let allBlogs;
try {
allBlogs = await blogs.find({}).populate("user");
} catch (err) {
return res.status(404).json(err);
}
res.status(200).json(allBlogs);
});
this is the route that sends all the blogs posted by all the users.
Interesting thing is that when I try to populate the user of a blogpost that is working exactly as expected it is populating the user of the blog from the users model however when I try to do the reverse that's not working. It is not populating all the blogs that a user has posted.

How to Join model in Mongodb(Mongoose) and express?

I have 3 models 'User' , 'Doctor', 'Appointment', I want to let the user make an appointment then when he get his appointment I want to return the doctor name, also when the doctor get the appointment I want t return the user Name.
User Model :
const mongoose = require('mongoose');
const User = mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
})
const User = mongoose.model('User', User);
module.exports = { User };
Doctor Model :
const mongoose = require('mongoose');
const Doctor = mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
})
const Doctor = mongoose.model('Doctor', Doctor);
module.exports = { Doctor };
Appointment Model :
const mongoose = require('mongoose');
const Appointment = mongoose.Schema({
date: {
type: Date,
},
time: {
type: Date
},
_userID: {
type: mongoose.Types.ObjectId,
ref: 'User'
},
_doctorID: {
type: mongoose.Types.ObjectId,
ref: 'Doctor'
}
})
const Appoitment = mongoose.model('Appoitment', Appointment);
module.exports = { Appoitment };
Make and Get Appointment :
const express = require('express');
const { Appointment } = require('../DataBase/Models/appointment.model');
const router = express.Router();
router.get("/appointment/:id", async (req, res) => {
try {
const appointment = await Appointment.find({
user: req.params.id,
}).populate({
path: "doctor",
model: "Doctor",
});
res.send({
status: 200,
message: "SuccessFull",
Appointments: appointment,
});
} catch (error) {
res.send({
status: 400,
message: `Error: ${error}`,
});
}
});
router.post("/appointment", async (req, res) => {
try {
const makeAppointment = new Appointment(req.body);
const result = await makeAppointment.save();
res.send({
status: 200,
message: "SuccessFull",
Appointment: result,
});
} catch (error) {
res.send({
status: 404,
message: `Error : ${error}`,
});
}
});
My Question is How I can return the Appointment with the doctor Name the same with the User Name ??
in the .populate method, the path param is the name of the attribute in the model that you're trying to retrieve, so instead of path: 'doctor', you should be using '_doctorID' because you used this as the attribute name in the Appointment Model.
The same works for your query in the .find, you're querying the 'user' attribute, but you have _userID in your appointment model.
So, you have to 2 options:
Change _userID and _doctorID to user and doctor, this way should be better;
Or change user and doctor in your controller to _userID and _doctorID;
If you follow the first option, your code now should be something like:
Appointment Model:
const mongoose = require('mongoose');
const Appointment = mongoose.Schema({
date: {
type: Date,
},
time: {
type: Date
},
user: {
type: mongoose.Types.ObjectId,
ref: 'User'
},
doctor: {
type: mongoose.Types.ObjectId,
ref: 'Doctor'
}
})
const Appoitment = mongoose.model('Appoitment', Appointment);
module.exports = { Appoitment };
Appointment Controller:
router.get("/appointment/:id", async (req, res) => {
try {
const appointment = await Appointment.find({
user: req.params.id,
})
.populate({
path: "doctor",
select: "_id name",
});
res.send({
status: 200,
message: "SuccessFull",
Appointments: appointment,
});
} catch (error) {
res.send({
status: 400,
message: `Error: ${error}`,
});
}
});
if you want to select specific column .
it will look like .populate('author', 'name'). // only return the Author name

How to add user's name as well as Id to users field in a chat?

I'm creating a web application that has chats, and users can join the chat. Once the user joins the chat, I want to add the user's ID as well as their name to the users field in the Chat schema. So far, I'm able to add their ID, but I am finding it difficult to add their name. Below, I have attached my Chat mongoose model, as well as my route to add a user to a chat. Also, I have attached my User mongoose model. Any help is greatly appreciated. Thank you!
Chat model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ChatSchema = new Schema({
title: {
type: String,
required: true
},
password: {
type: String,
required: true
},
creator: {
type: Schema.Types.ObjectId,
ref: 'user'
},
users: [
{
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
name: {
type: String,
required: true
}
}
],
code: {
type: String,
required: true
},
posts: [
{
text: {
type: String,
required: true
},
title: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Chat = mongoose.model('chat', ChatSchema);
route to add user to chat:
// #route Put api/chats
// #desc Add a user to a chat
// #access Private
router.put('/', [auth,
[
check(
'code',
'Please include the code for the chat')
.not()
.isEmpty(),
check(
'password',
'Please include the password for the chat'
).not()
.isEmpty()
]
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
try {
const chat = await Chat.findOne({ code: req.body.code });
//const user = await User.findOne({ user: req.user.id });
if (!chat) {
return res.status(400).json({ msg: 'Invalid Credentials' });
}
// Check if the chat has already been joined by the user
if (chat.users.filter(member => member.user.toString() === req.user.id).length > 0) {
return res.status(400).json({ msg: 'Chat already joined' });
}
//console.log(chat.password);
const isMatch = await bcrypt.compare(req.body.password, chat.password);
if (!isMatch) {
return res.status(400).json({ errors: [{ msg: 'Invalid Credentials' }] });
}
const newUser = {
user: req.user.id,
text: req.user.name
}
chat.users.unshift(newUser);
await chat.save();
res.json(chat.users);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
User model:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
module.exports = User = mongoose.model('user', UserSchema);
in this part, it seems you are assigning the user's name to a text property, which I think it should be name not text.
const newUser = {
user: req.user.id,
text: req.user.name
}
The code should be:
const newUser = {
user: req.user.id,
name: req.user.name //Property should be name
}
I hope this works!

how to fetch user details from populated table in nodejs?

I have two tables in my MongoDB cluster i.e Post and User. Actually I want to retrieve the username and userID along with a post from the post table when a user posts something.
my post controller
router.getPostsList = async (req, res) => {
try {
const posts = await Post.list();
return res.status(200).json(posts);
} catch (err) {
return res.status(400).json(err);
}
};
MongoDB Post collection Image
PostSchema
const PostSchema = new mongoose.Schema(
{
text: {
type: String,
trim: true
},
slug: {
type: String,
trim: true,
lowercase: true
},
user: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
]
},
{ timestamps: true }
);

Manually populating Mongodb field on document creation with Mongoose

Following the Mongoose documentation, I was able to create two docs, but am unable to populate one with the other.
Despite manually setting the 'account' value to reference the other document, my database doesn't seem to create the relation.
Below is the code I've used:
UserAuth.findOne({ email }, (err, user) => {
if (err) return done(err);
if (user) {
return done(null, false,
{ message: 'It appears that email address has already been used to sign up!' });
}
// Create the user account
const newAccount = new UserAccount({
name: {
first: req.body.firstName,
last: req.body.lastName,
},
});
newAccount.save((err) => {
if (err) throw err;
// Create the user authentication
const newAuth = new UserAuth({
email,
account: newAccount,
});
newAuth.password = newAuth.generateHash(password);
newAuth.save((err) => {
if (err) throw err;
return done(null, newAuth);
});
return done(null, newAccount);
});
});
Collections:
User Auth
const UserAuthSchema = new Schema({
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
account: {
type: Schema.Types.ObjectId,
ref: 'User',
},
});
module.exports = mongoose.model('UserAuth', UserAuthSchema);
User Account
const UserSchema = new Schema({
name: {
first: {
type: String,
required: true,
},
last: {
type: String,
required: true,
},
},
team: {
type: Schema.Types.ObjectId,
ref: 'Team',
},
image: {
type: String,
default: 'assets/default_user.png',
},
});
module.exports = mongoose.model('User', UserSchema);
It looks like the part:
// Create the user authentication
const newAuth = new UserAuth({
email,
account: newAccount,
});
should be:
// Create the user authentication
const newAuth = new UserAuth({
email,
account: newAccount._id,
});
And then, when you query the collection, you have to say which field should be populate, as shown in (Mongoose documentation)[http://mongoosejs.com/docs/populate.html]
Ad please check that the types of the 2 linked fields are the same as mentioned in the documentation.

Resources