I am facing issue with chaining .populate() method in mongoose - node.js

This is my user Schema where I have addresses as array
name: {
type: String,
unique: true,
require: true
},
email: {
type: String,
trim: true,
lowercase: true,
unique: true,
required: "Email address is required"
},
password: {
type: String,
required: true,
min: [6, "Password must be atlest 6 characters length"]
},
mobile: {
type: String,
required: true,
unique: true
},
image: {
type: String,
default: "gravatar.png"
},
addresses: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Address"
}
],
cart: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Cart"
}
],
orderHistory: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "OrderHistory"
}
]
});
This is post request to /user/address route where I want to create a new Address, link the user collection and address collection and populate the user collection. But it is giving me an error
"TypeError: Address.create(...).then(...).populate is not a function". I also used exec() method. I think I am not using populate and exec method correctly.
router.post("/address", function(req, res) {
console.log("form data: ", req.body);
Address.create(req.body)
.then(function(newAddr) {
// console.log(newAddr);
return User.findByIdAndUpdate(
{ _id: req.session.user._id },
{ $push: { addresses: newAddr._id } },
{ new: true }
);
})
.populate("addresses")
// .exec((err, updatedUser) => {
// if (err) {
// res.send(err);
// } else {
// console.log(updatedUser);
// res.redirect("/user");
// }
// });
.then(function(updatedUser) {
res.redirect("/user");
})
.catch(err => {
res.send(err);
});
});

Related

Adding a field to a nested document in mongoDB node js

Hello since there is not subcollections in mongodb i have found that you can nest document as an array ! i did that and it worked but what i want is to add a field to that existing array without losing the old ones ! i can do that by fetching the old array and adding the new field to it and returning that array but doing the fetch inside the patch method wouldn't be a good approach ! so is there any other way i can make that happen ?
Modal :
const mongoose = require("mongoose");
const notificationSchema = new mongoose.Schema(
{
notificationType: {
type: String,
required: false,
},
message: { type: String, required: true },
},
{
timestamps: true,
}
);
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
passwordHash: {
type: String,
required: true,
},
phone: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
default: false,
},
street: {
type: String,
default: "",
},
notifications: [notificationSchema],
apartment: {
type: String,
default: "",
},
zip: {
type: String,
default: "",
},
city: {
type: String,
default: "",
},
country: {
type: String,
default: "",
},
});
exports.User = mongoose.model("User", userSchema);
exports.Notification = mongoose.model("Notification", notificationSchema);
router.patch("/:id", async (req, res) => {
try {
console.log("hh");
const user = await User.findByIdAndUpdate(req.params.id, {
notifications: [
{
notificationType: "Order",
message: "New Notification",
},
],
});
if (!user) {
return res.status(404).send("The user cannot be found");
}
res.send(user);
} catch (error) {
return res.status(400).json({ success: false, error });
}
});

Find one and Update mongoose in Node js

I have following code for a chat application based on socket io.
const query={ chatID: chatId }
const update= {
$push: {
messages:{
message: message,
sendBy: sendById,
sendTo: sendTo
}
}
}
const options={upsert: true, new:true}
Chat.findOneAndUpdate(query, update, options, function(error, result) {
if (error){
console.log("error: "+error.message);
return;
}
io.emit("message", result.messages)
}).clone();
now if the chat id doesn't exists it creates new with query and update. But i want it like,
if the query doesnt exist, i have some more params to add to the document. How can i achieve that.
if i add the whole params in query , it wont find the document.
the foloowing is my schema
const ChatSchema = mongoose.Schema({
chatID: { type: String, required: true, unique: true },
participants: [
{ senderId: { type: mongoose.Types.ObjectId, unique: true, required: true } },
{ receiverId: { type: mongoose.Types.ObjectId, unique: true, required: true } }
],
messages: [
{
message: { type: String, required: true },
sendBy: { type: String, required: true },
sendTo: { type: String, required: true },
seen: { type: Boolean, default: false },
date: { type: Date, default: Date.now() }
},
],
})

Problem with update a single doc in monogdb using express and mongoose

I'm quiet new to mongodb and I'm actually trying to implement a follow-unfollow method in the backend
there are two types of users in the database
Mentors and mentees
only mentees can follow the mentors and mentors can only accept the request
the schema
Mentors
const MentorsSchema = mongoose.Schema({
name: { type: String, required: true },
designation: { type: String, required: true },
yearNdClass: {
type: String,
required: ["true", "year and class must be spciefied"],
},
respondIn: { type: String, required: true },
tags: {
type: [String],
validate: (v) => v == null || v.length > 0,
},
socialLinks: {
github: { type: String, default: "" },
twitter: { type: String, default: "" },
facebook: { type: String, default: "" },
instagram: { type: String, default: "" },
},
watNum: { type: Number, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
about: { type: String },
followers: [
{ type: mongoose.Schema.Types.ObjectId, ref: "Mentees", default: "" },
],
pending: [
{ type: mongoose.Schema.Types.ObjectId, ref: "Mentees", default: "" },
],
});
Mentee
const MenteeSchema = mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
yearNdClass: {
type: String,
required: ["true", "year and class must be spciefied"],
},
socialLinks: {
github: { type: String },
twitter: { type: String },
facebook: { type: String },
instagram: { type: String },
},
about: { type: String },
skillLooksFor: { type: String, required: true },
watNum: { type: Number, required: true },
following: [{ type: mongoose.Schema.Types.ObjectId, ref: "Mentors",default:"" },
],
});
you can see that there are two fields for mentors both following and pending arrays which consist of the ids of the mentees who follow the mentors and the ids of the mentees which yet to be accepted as a follower
I planned to create an endpoint where when a mentee gives a follow request it should be reached into the mentor pending array so that he can accept it later
so my logic like this
// #desc follow a mentor
// #route POST /api/mentees/follow-mentor/:id
// #access private
menteeRoute.post(
"/follow-mentor/:id",
isAuthorisedMentee,
expressAsyncHandler(async (req, res) => {
const { id } = req.params;
const mentee = await Mentees.findById(req.mentee.id);
const mentor = await Mentors.findById(id).select("-password");
// console.log(mentor)
if (mentee) {
try {
await Mentees.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(id) },
{ $addToSet: { "following.0": mentor._id } },
{ new: true }
);
await Mentors.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(mentor._id) },
{
$addToSet: {
"pending.0": id,
},
},
{ new: true },
);
res.json({
data: {
mentor,
mentee,
},
});
} catch (error) {
console.log(error);
throw new Error(error);
}
}
})
);
but the code didn't work.
can anyone help me to resolve the problem?
basically, when a mentee gives a follow request it should update the following array of mentee with the id of mentor and it should also update the pending array of mentor with the id of the mentee
PS: any alternative ideas are also welcome
Try to remove the .0 index and use the $push method.
Also, you should return the updated objects:
menteeRoute.post(
'/follow-mentor/:id',
isAuthorisedMentee,
expressAsyncHandler(async (req, res) => {
const { id } = req.params;
const mentee = await Mentees.findById(req.mentee.id);
const mentor = await Mentors.findById(id).select('-password');
// console.log(mentor)
if (mentee) {
try {
const updatedMentee = await Mentees.findOneAndUpdate(
{ _id: mongoose.Types.ObjectId(id) },
{ $push: { following: mentor._id } },
{ new: true }
);
const updatedMentor = await Mentors.findOneAndUpdate(
{ _id: mentor._id },
{
$push: {
pending: id,
},
},
{ new: true }
);
res.json({
data: {
mentor: updatedMentor,
mentee: updatedMentee,
},
});
} catch (error) {
console.log(error);
throw new Error(error);
}
}
})
);

How to correctly save references to mongodb from request

I want to save data and references of child document into parent document from request, I have managed to achieve that, but I am not sure is this correct way of doing it.
I have found in stackoverflow that first we have to save child document. so we can save references of child document into parent document
This is my structure of request
"category": "movie",
"overview": "This is overview",
"poster_path": "https://image.tmdb.org/t/p/w500/aWeKITRFbbwY8txG5uCj4rMCfSP.jpg",
"release_date": "2021-12-01",
"title": "Sing 2",
"vote_average": 8.2,
"cast": [
{
"name": "Matthew McConaughey",
"profile_path": "wJiGedOCZhwMx9DezY8uwbNxmAY.jpg"
},
{
"name": "Reese Witherspoon",
"profile_path": "6Pp3BrY2JbJg77Po8NOBO6zOA8m.jpg"
}
]}
//Show Schema
const showSchema = new Schema({
title: {
type: String,
unique: true,
required: [true, 'Title can not be empty.'],
trim: true,
text: true
},
slug: String,
poster_path: {
type: String,
required: [true, 'Cover can not be empty.'],
trim: true
},
overview: {
type: String,
required: [true, 'Description can not be empty.'],
trim: true,
text: true
},
release_date: {
type: Date,
default: Date.now(),
required: [true, 'Release date can not be empty.']
},
category: {
type: String,
trim: true,
required: [true, 'Please provide category']
},
vote_average: {
type: Number,
min: [1, 'Rating must be 1 or above 1'],
max: [10, 'Rating must be 10 or below 10']
},
vote_count: {
type: Number,
default: 0
},
cast: [
{
type: mongoose.Schema.ObjectId,
ref: 'Cast'
}
]
})
//Create slug
showSchema.pre('save', function(next) {
this.slug = slugify(this.title, {lower: true})
next()
})
showSchema.pre(/^find/, function (next) {
this.populate({
path: 'cast',
select: '-__v'
})
next()
})
//Cast Schema
const castSchema = new Schema({
name: {
type: String,
trim: true,
text: true,
unique: true,
required: [true, 'Please provide name of actor']
},
profile_path: {
type: String
}
})
And this is how I did it
exports.add = async (req, res) => {
const show = {
category: req.body.category,
overview: req.body.overview,
poster_path: req.body.poster_path,
release_date: req.body.release_date,
title: req.body.title,
vote_average: req.body.vote_average,
}
try {
Cast.insertMany(req.body.cast, function(error, createdCast){
if(error){
console.log('Cast', error)
return
}
Show.create(show, function(error, createdShow){
if(error){
console.log('Show', error)
return
}
createdCast.forEach(element => {
createdShow.cast.push(element._id)
});
createdShow.save(function(error, show){
if(error){
return
}
console.log('saved Show', show)
})
})
})
} catch (error) {
console.log(error)
res.status(400).json({
message: 'fail',
error: error
})
}
}

Add data in an array of object with mongoDB

I need your help, I try to add(if it not exists) or update if exists datas in an array of Object in MongoDB.
Here is my Model
import { Schema, model } from "mongoose";
const userSchema = new Schema({
firstName: {
type: String,
required: true,
unique: false,
trim: true
},
pseudo: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
email: {
type: String,
required: false,
trim: true
},
password: {
type: String,
required: true
},
// password2: {
// type: String,
// required: true
// },
tags: {
type: Array,
required: false
},
address: {
type: String,
required: true,
unique: false,
trim: true
},
coord: {
type: Object,
required: false,
unique: false,
trim: true
},
poll: [
{
tag: String,
dates: Array
}
]
},
{
timestamps: true,
});
const User = model('User', userSchema);
export default User;
My route
router.route('/calendar/:email').post((req, res) => {
User.findOne({ email: req.body.email }).then( (user) =>{
console.log("user 1", user)
User.bulkWrite([
{
insertOne: {
"poll": {
"tag": req.body.selectedTag,
"dates": req.body.datesArray
}
}
},
{
updateOne: {
"filter": {
"tag" : req.body.selectedTag
},
"update": {
$set: {
"dates": req.body.datesArray
}
},
}
}
])
})
});
and the datas sended :
email: 'john#gmail.com',
selectedTag: 'work',
dateArray: [ '2020-07-16T22:00:00.000Z' ]
I try many things like by findOneaAndUpdate, but I don't know how to add in the array "poll", objects with tag and the dates associated.
If somebody could help me it would be very nice !
I shoul use add $addToSet or $push, depending if the element is unique or not.
Something like this:
"update": {
"$addToSet": {
"poll": { /*...*/ }
}
}
For reference:
http://docs.mongodb.org/manual/reference/operator/update/addToSet/
http://docs.mongodb.org/manual/reference/operator/update/push/

Resources