Post an array of objects ExpressJs Mongoose NodeJs - javascript

UPDATE
I have a mongoose schema and express controller, now I have to post an Array of Objects based on that schema, I have to post like 30 Objets, here is an example of two I posted and I received that response, and I wanto to see the Array of all Objects.
CoursesModel.ts
const CoursesSchema = new Schema({
courses: [{
course_status: String,
course_code: String,
course_name: req.body.course_name,
institute_name: String,
hour_duration: Number,
modality: String,
schedule: String,
start_date: Date,
finish_date: Date,
enroll_date_limit: Date,
course_value: Number,
}],
created_at: {
type: Date,
default: Date.now
}
});
coursesController.ts // createCourse
const Courses = CoursesModel;
public createCourses(req: Request, res: Response) {
try {
if (!req.body) {
throw new Error(`Is missing parameter : Table data`);
}
const createCourse = {
courses: [{
course_status: req.body.course_status,
course_code: req.body.course_code,
course_name: req.body.course_name,
institute_name: req.body.institute_name,
hour_duration: req.body.hour_duration,
modality: req.body.modality,
schedule: req.body.schedule,
start_date: req.body.start_date,
finish_date: req.body.finish_date,
enroll_date_limit: req.body.enroll_date_limit,
course_value: req.body.course_value,
}],
created_at: new Date()
};
let newCourses = new Courses(createCourse);
newCourses.save().then(data => {
res.json(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the course"
});
})
);
} catch (error) {
this.logger.error({
data: req.body,
error: error,
source: 'Error in function createCourses'
});
res.status(500);
return res.send({ error: (error.message) ? error.message : "Internal server error" });
}
}
Json body I post on Insomnia
{"courses":[{
"course_status": "Active",
"course_code": "0004",
"institute_name": "Berkley",
"course_name": "Programming",
"month_duration": 2,
"hour_duration": 120,
"modality": "Virtual",
"schedule": "2 a 5",
"start_date": "2021-07-02T05:00:16.000Z",
"finish_date": "2021-07-02T05:00:16.000Z",
"enroll_date_limit": "2021-07-02T05:00:16.000Z",
"course_value": 300000,
},
{
"course_status": "Active",
"course_code": "0005",
"institute_name": "MIT",
"course_name": "Digital Marketing",
"hour_duration": 120,
"modality": "Virtual",
"schedule": "2 a 5",
"start_date": "2021-07-02T05:00:16.000Z",
"finish_date": "2021-07-02T05:00:16.000Z",
"enroll_date_limit": "2021-07-02T05:00:16.000Z",
"course_value": 300000,
}]}
This is what I get from Insomnia
Insomnia response
{
"successfully": true,
"data": {
"_id": "5f1ae0e3cf5d702706b5bb09",
"courses": [
{
"_id": "5f1ae0e3cf5d702706b5bb0a"
}
],
"created_at": "2020-07-24T13:23:47.173Z",
"__v": 0
}
}

I solve in this way
const Courses = CoursesModel;
public async createCourses(req: Request, res: Response) {
try {
if (!req.body) {
throw new Error(`Is missing parameter : Table data`);
}
const courses = []
for(const course of req.body.courses){
const tableCourse ={
course_status: course.course_status,
course_code: course.course_code,
course_name: course.course_name,
institute_name: course.institute_name,
hour_duration: course.hour_duration,
modality: course.modality,
schedule: course.schedule,
start_date: course.start_date,
finish_date: course.finish_date,
enroll_date_limit: course.enroll_date_limit,
course_value: course.course_value,
created_at: new Date()
};
let newCourses = new Courses(tableCourse);
const newCourses = await newTableCourses.save()
courses.push(newCourses)
}
res.json({ successfully: true, data: { courses } });
} catch (error) {
this.logger.error({
data: req.body,
error: error,
source: 'Some error occurred while creating the course.'
});
res.status(500);
return res.send({ error: (error.message) ? error.message : "Internal server error" });
}
}
CourseModel.ts
const CoursesSchema = new Schema({
course_status: String,
course_code: String,
course_name: req.body.course_name,
institute_name: String,
hour_duration: Number,
modality: String,
schedule: String,
start_date: Date,
finish_date: Date,
enroll_date_limit: Date,
course_value: Number,
created_at: {
type: Date,
default: Date.now
}
});

Use res.json(data) instead of res.send(data) and instead of return from directly use save
const Courses = CoursesModel;
public createCourses(req: Request, res: Response) {
try {
if (!req.body) {
throw new Error(`Is missing parameter : Table data`);
}
const createCourse =Courses ({
courses: [{
course_status: req.body.course_status,
course_code: req.body.course_code,
course_name: req.body.course_name,
institute_name: req.body.institute_name,
hour_duration: req.body.hour_duration,
modality: req.body.modality,
schedule: req.body.schedule,
start_date: req.body.start_date,
finish_date: req.body.finish_date,
enroll_date_limit: req.body.enroll_date_limit,
course_value: req.body.course_value,
}],
created_at: new Date()
});
newCourses.save().then(data => {
res.json(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the course"
});
})
);
} catch (error) {
this.logger.error({
data: req.body,
error: error,
source: 'Error in function createCourses'
});
res.status(500);
return res.send({ error: (error.message) ? error.message : "Internal server error" });
}
}

Related

Mongoose mixed Type object array, can findOneAndUpdate

I have a controller edit card which updates the fields of cardsArray object.
cardsArray is mixed type object as fileds of each card object is different so i am storing mixed.type
Althought pushing new card using addCard controller works perfectly
But when edit card controller is called, it gives type error
When edit Controlller is callled is gives following error:
TypeError: Cannot read properties of null (reading 'cardsArray')
// Schema
const userSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
cardsArray: [{ type: mongoose.Schema.Types.Mixed }],
}
);
//__Mongodb Data
{
"_id": {
"$oid": "63b43ab32fc8d3c100cafecc"
},
"name": "usern_name",
"email": "pr****#gmail.com",
"password": "$2b$12$3nwifHakrBu94BwLXAC4Nu16Kw0.xyW8vAIPTMSgY7cYttVklDIZq",
"cardsArray": [
{
"title": "some_title",
"category": "Bank",
"cardHolder": "some_name",
"cardNumber": "54545454",
"expiry": "23/01",
"cvv": "***",
"logoIndex": 72,
"isFavourite": false,
"_id": {
"$oid": "63b83cc77288d277ef359533"
}
}
],
"loginIdsArray": [],
"docsArray": [],
"activitiesArray": [],
"__v": 0
}
// Add Card Controller.js___
addCard: async (req, res) => {
console.log(req.body.data, req.body.user_id)
// console.log('obj_id', newObjectId)
req.body.data._id = newObjectId;
try {
const response = await UserDatabase.findOneAndUpdate(
{ _id: req.body.user_id },
{
$push: {
// cardsArray: req.body.data,
cardsArray: { $each: [req.body.data] },
},
},
{ returnOriginal: false }
);
res.status(200).send(response);
} catch (error) {
console.log(error)
res.status(404).json({ message: error.message });
}
},
// edit card controller.js
editCard: async (req, res) => {
const id = req.params.id;
const { category, title, cardHolder, cardNumber, expiry, cvv, logoIndex, isFavourite } = req.body;
console.log(req.params.id)
try {
const response = await UserDatabase.findOneAndUpdate(
{ _id: "63b43ab32fc8d3c100cafecc", 'cardsArray._id': "63b709fc69a1cfa6fccd645c" },
{
$set: {
"cardsArray.$.title": req.body.title,
"cardsArray.$.category": req.body.category,
"cardsArray.$.cardHolder": req.body.cardHolder,
"cardsArray.$.cardNumber": req.body.cardNumber,
"cardsArray.$.expiry": req.body.expiry,
"cardsArray.$.cvv": req.body.cvv,
"cardsArray.$.logoIndex": req.body.logoIndex,
"cardsArray.$.isFavourite": req.body.isFavourite
}
},
);
console.log(response)
res.status(201).json(response.cardsArray);
} catch (error) {
console.log(error)
res.status(404).json({ message: error.message });
}
}
it means that there is no data matching the following _id and cardsArray._id
i thinks so its fails to find the feild 'cardsArray._id',first try finding the value by just findOne
await UserDatabase.findOneAndUpdate(
{ _id: "63b43ab32fc8d3c100cafecc", 'cardsArray._id': "63b709fc69a1cfa6fccd645c" })
if your find doesn't work try below methord not sure but it may work you have to either find the id and loop through the cardsArray of use $in or $match
await UserDatabase.findOneAndUpdate(
{ _id: "63b43ab32fc8d3c100cafecc", 'cardsArray':{$in:[ {_id:"63b709fc69a1cfa6fccd645c" }]})

MongoDB API from express

Have a model
const mongoose = require("mongoose");
const botSchema = new mongoose.Schema({
code: {
type: String,
required: true,
unique: true,
},
description: {
type: String,
required: true,
},
botStatus: {
type: String,
required: true,
},
});
// botSchema.plugin(require("mongoose-beautiful-unique-validation"));
module.exports = mongoose.model("Bot", botSchema);
route =====
// Creating one
router.post("/", async (req, res) => {
const bot = new Bot({
code: req.body.code,
description: req.body.description,
botStatus: req.body.botStatus,
});
try {
const newBot = await bot.save();
res.status(201).json(newBot);
} catch (err) {
res.status(400).json({ message: err.message });
}
});
==== when post using postman or Rest Client from VS Code
POST http://localhost:4000/bots
Content-Type: application/json
{
"code": "code 04",
"description": "desc 04",
"botStatus": "status 04"
}
it gives me the error
{
"message": "E11000 duplicate key error collection: botmanager.bots index: route_id_1 dup key: { route_id: null }"
}
I have no ideas where is route_id_1 dup key is coming from

Unable to get the values from one schema to another schema

I create a order schema which have two models; StudentConsessionSchema and consessionSchema
StudentConsessionSchema acquire the student model (student model contain the details about the student).
The other model consessionSchema acquire the StudentConsessionSchema (for acquiring the student details).
When I test it in postman to order it works but it's not able to get the student details in consessionSchema.
order schema:
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const StudentConsessionSchema = new mongoose.Schema({
student: {
type: ObjectId,
ref: "Student", //ref to the student model from another file
},
FullName: {
type: String,
},
addmissionNumber: {
type: String,
required: true,
trim: true,
maxlength: 8,
},
faculty: {
type: ObjectId, //ref to the faculty model from another file
ref: "Faculty",
required: true,
},
});
const StudentConsession = mongoose.model(
"StudentConsession",
StudentConsessionSchema
);
const consessionSchema = new mongoose.Schema(
{
student: [StudentConsessionSchema], //this returns [] empty array
consession_id: {},
fromStation: {
type: String,
required: true,
},
toStation: {
type: String,
default: "Dadar",
},
passType: {
type: String,
enum: ["I", "II"],
required: true,
},
ticketPeriod: {
type: String,
enum: ["Monthly", "Quarterly"],
default: "Monthly",
required: true,
},
status: {
type: String,
default: "Pending",
enum: ["Pending", "Cancelled", "Accepted", "Printed"],
},
updated: Date,
},
{ timestamps: true }
);
const Consession = mongoose.model("Consession", consessionSchema);
module.exports = { StudentConsession, Consession };
create order controller:
exports.createOrder = (req, res) => {
let form = new formidable.IncomingForm();
form.keepExtensions = true;
form.parse(req, (err, fields) => {
const {
admissionNumber,
fullName,
faculty,
fromStation,
toStation,
passType,
ticketPeriod,
} = fields;
if (
!admissionNumber ||
!fullName ||
!faculty ||
!fromStation ||
!toStation ||
!passType ||
!ticketPeriod
) {
return res.status(400).json({
error: "Please fill all fields",
});
}
let consession = new Consession(fields);
// const consession = new Consession(req.body.consession);
if (req.student.pass === 1) {
return res.status(400).json({
error:
"You are not eligible to make request Because You already have a pass",
});
}
consession.save((err, order) => {
if (err) {
console.log(err);
return res.status(400).json({
error: "Failed to make order",
});
}
res.json(order);
});
});
};
output:
{
"toStation": "abc",
"ticketPeriod": "Monthly",
"status": "Pending",
"_id": "600e789887b9a201bc4c2d1a",
"fromStation": "xyz",
"passType": "II",
"student": [],
"createdAt": "2021-01-25T07:51:52.091Z",
"updatedAt": "2021-01-25T07:51:52.091Z",
"__v": 0
}
My questions is why is the student array empty?

Find One and Update in Mongoose with reference to other models is not working

I have a model named OrderModel and it has reference to other models as well
const orderSchema = new Schema({
_id: Schema.Types.ObjectId,
address: { type: addressSchema, required: false },
items: [{ type: Schema.Types.ObjectId, ref: 'Items' }],
date: { type: Date, default: moment(new Date()) },
user: { type: Schema.Types.ObjectId, ref: 'Users' },
is_completed: { type: Boolean, required: true, default: false },
is_canceled: { type: Boolean, required: true, default: false }
});
and when I want to update this model, using PATCH, it is giving me an error,
CastError: Cast to [ObjectId] failed for value "["5f0c9493f833e23a0028bd31,5f0c9429f833e23a0028bd2f"]" at path "items"
Here is how I do it in my code,
router.patch('/order', (req, res) => {
const query = { _id: req.body._id };
const _token = req.headers.authorization;
let data = req.body;
jwt.verify(_token, process.env.AUTH_TOKEN_KEY, (err, decoded) => {
console.log(query);
if (err) {
res.json({ message: 'Token Invalid'.err });
} else {
OrderModel.findOneAndUpdate(query, data, { new: true }, (err, doc) => {
console.log(doc,query);
if (doc) {
return res.json({ message: 'Succesfully saved', data: doc });
}
return res.json({ message: `No order found for id ${req.body._id}` });
});
}
})
})
i have two items as an Array, sent from frontend
{
"_id": "5f8f1b7b29cbed4a8495d646",
"items":"5f0c9493f833e23a0028bd31,5f0c9429f833e23a0028bd2f",
"user":"5f06060110b7881ac0244005",
"address":{
"line_1": "Address line 1",
"line_2": "Address line 1",
"city": "Los Angeles",
"state": "California",
"pin": "90210"
},
"is_completed": false,
"is_canceled": false
}
what am i doing wrong here?

How can i iterate mongoose returned documents array in loop using mongoose?

I have a node.js(express based) server in which i have a function which returns all users. Here is the function.
export async function findAllUser() {
let users = await User.find({}).exec()
return users
}
In my node.js applicaiton i have two models(schema) of Users and Referrals like this .
var User = mongoose.model(
"users",
new Schema({
first_name: String,
last_name: String,
name: String,
email: String,
password: String,
roleId: { type: Number, default: 0 },
country: String,
token: String,
createdAt: String,
updatedAt: String,
tempToken: String,
verificationCode: String,
fbUserId: String,
isFbUser: { type: Boolean, default: false },
isActive: { type: Boolean, default: true },
isEmailVerified: { type: Boolean, default: false },
rememberme: Boolean,
}, {
toJSON: { virtuals: true },
toObject: { virtuals: true }
})
);
User.virtual("referrals", {
ref: "referralLinks",
foreignField: "userId",
localField: "_id"
});
export var ReferralLink = mongoose.model(
"referralLinks",
new Schema({
referral_link: String,
referral_code: String,
isLink: Number,
offer_name: String,
offer_desc: String,
user_email: String,
companyId: { type: Schema.Types.ObjectId, ref: 'companies' },
addedByAdmin: { type: Boolean, default: true },
number_of_clicks: Number,
referral_country: String,
link_status: String,
categoryId: { type: Schema.Types.ObjectId, ref: 'categories' },
number_of_clicks: { type: Number, default: 0 },
createdAt: String,
updatedAt: String,
userId: { type: Schema.Types.ObjectId, ref: 'users' }
})
);
I have my separate api.route.js file in which i have get all users route like this
router.get("/", log, getAllUsers);
And i my api.controller.js file i have getAllUsers like this
export async function getAllUsers(req, res) {
try {
let Users = await findAllUser()
if (Users) {
generateResponse(true, "All Users fetched", Users, res)
} else {
generateResponse(false, "No Users found", null, res)
}
} catch (err) {
generateResponse(false, 'Error occured, 404 not found!', err, res)
}
}
And in my api.handler.js file i have findAllUser function like this
export async function findAllUser() {
let users = await User.find({}).populate("referrals").exec()
return users
}
Single user can have more than one Referrals. But unfortunately i don't have 'Referrals' reference _id in Users document. Now, i want to get all users with their respective Referrals
I am getting all users correctly but for each user i also want to fetch all their respective referrals. So for that i definitely can't use for or forEach loop because of async nature of mongoose find. So what should i use instead of for or forEach loop?
My desired results
results = [
{
first_name : "Fahad",
last_name : "subzwari",
email : "fahadsubzwari#gmail.com",
password : "***",
referrals : [
{
//referral object 1
},
{
//referral object 2 ...
}
]
},
{
first_name : "Alex",
last_name : "Hales",
email : "alex#gmail.com",
password : "***",
referrals : [
{
//referral object 1
},
{
//referral object 2 ...
},
{
//referral object 3 ...
}
]
},
]
To be able to access referrals from user you need to use virtual populate.
So your userSchema must be like this:
const userSchema = new Schema(
{
first_name: String,
last_name: String,
name: String,
email: String,
password: String,
roleId: { type: Number, default: 0 },
country: String,
token: String,
createdAt: String,
updatedAt: String,
tempToken: String,
verificationCode: String,
fbUserId: String,
isFbUser: { type: Boolean, default: false },
isActive: { type: Boolean, default: true },
isEmailVerified: { type: Boolean, default: false },
rememberme: Boolean
},
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
// Virtual populate
userSchema.virtual("referrals", {
ref: "referralLinks",
foreignField: "userId",
localField: "_id"
});
var User = mongoose.model("users", userSchema);
And now you can use this route to access referrals from users:
router.get("/", async (req, res) => {
const result = await User.find({}).populate("referrals");
res.send(result);
});
The result will be like this: ( I excluded some fields for simplicity)
[
{
"_id": "5dd6819201419f5930d02334",
"name": "User 1",
"email": "user1#gmail.com",
"password": "123123",
"__v": 0,
"referrals": [
{
"_id": "5dd6829831b95a6b2cd58fca",
"referral_link": "referral_link 1",
"userId": "5dd6819201419f5930d02334",
"__v": 0
},
{
"_id": "5dd682a031b95a6b2cd58fcb",
"referral_link": "referral_link 2",
"userId": "5dd6819201419f5930d02334",
"__v": 0
}
],
"id": "5dd6819201419f5930d02334"
},
{
"_id": "5dd681a101419f5930d02335",
"name": "User 2",
"email": "user2#gmail.com",
"password": "123123",
"__v": 0,
"referrals": [
{
"_id": "5dd682a731b95a6b2cd58fcc",
"referral_link": "referral_link 3",
"userId": "5dd681a101419f5930d02335",
"__v": 0
}
],
"id": "5dd681a101419f5930d02335"
}
]
UPDATE:
Here is the steps for your project setup:
api.handler.js:
exports.findAllUser = async function() {
console.log("api handler inside");
let users = await User.find({})
.populate("referrals")
.exec();
console.log("in handler: ", users);
return users;
};
api.controller.js:
const handler = require("./api.handler");
exports.getAllUsers = async function(req, res) {
console.log("userController.getAllUsers");
try {
let Users = await handler.findAllUser();
if (Users) {
return res.send(Users);
generateResponse(true, "All Users fetched", Users, res);
} else {
generateResponse(false, "No Users found", null, res);
}
} catch (err) {
generateResponse(false, "Error occured, 404 not found!", err, res);
}
};
api.route.js
const apiController = require("../controllers/api.controller");
router.get("/", log, apiController.getAllUsers);
You say "i don't have 'Referrals' reference _id in Users" so I assume you have a reference to the user in the Referrals schema?
Otherwise, with no way to link them you are lost at sea I'm afraid... :-(
If you do then you would do it in a separate query:
const userIds = users.map(user => user._id);
const referrals = await Referrals.find({ userId: { $in: userIds } })
The $in operator will grab any field where the user id is included in the array.
EDIT: In response to your update - yes the above should work fine. Then you can do what you want with them e.g. map the referrals to the user objects, or use them individually etc. etc.
EDIT2: Yep this is the way. At this point you have an array of users and an array of referrals so you just need to put them together.
users.map(user => ({
// add props from user obj
...user,
// add all referrals that with matching userId
referrals: referrals.filter(referral => referral.userId === user._id)
}))
Remember that as you are dealing with asynchronous calls and promises so you will either need to use the async/await keywords, or parse the results in the promise callback.

Categories