Having trouble pushing sub document to parent array - javascript

I have a users model which includes a locationsSchema in it:
const locationSchema = require('./location.js');
const userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
},
token: {
type: String,
require: true,
},
locations: [locationSchema],
passwordDigest: String,
}, {
timestamps: true,
});
My locations model is :
const mongoose = require('mongoose');
const locationSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
city: {
type: String,
},
region: {
type: String,
},
country: {
type: String,
},
coords: {
lat: {
type: Number,
require: true
},
long: {
type: Number,
require: true
},
},
visited: {
type: Boolean,
require: true,
default: false,
},
comment: {
type: String,
},
}, {
timestamps: true,
});
and finally the create action in my controller for locations is:
const controller = require('lib/wiring/controller');
const models = require('app/models');
const User = models.user;
const Location = models.location;
const create = (req, res, next) => {
User.findById(req.body.user.id).then (function(user){
let location = Object.assign(req.body.location);
user.locations.push(location);
return user.save();
})
.then(user => res.json({ user }))
.catch(err => next(err));
};
When I try to send a curl POST request to locations I get:
{"error":{"message":"this._schema.caster.cast is not a function","error":{}}}
console.logging user, user.locations, and locations just before the
user.locations.push(location);
line returns exactly what I'd expect. I'm fairly certain the error is stemming from the push function call. Any insight would be much appreciated.

your embedding location model
const locationSchema = require('./location.js');
so only you getting this error,
model can't be embedding schema only embedding
const locationSchema = require('./location.js'). schema;
so you try this

Related

how to wait for variable update for new calculation in javascript

Hey I'm trying to build dashboard for calculate my medicine supplier total outstanding using nextjs.
*below *is my **createPurchase **api.
`
import PurchaseOrder from '../../models/PurchaseOrder'
import Supplier from '../../models/Supplier'
import connectDB from '../../middleware/mongoose';
import Medicine from '../../models/Medicine';
const handler = async (req, res) => {
if (req.method === 'POST') {
const medicines = [];
let totalOrderAmount = 0;
let totalPaybleGst = 0;
req.body.medicines.forEach(async medicine => {
let medicineOne = await Medicine.findById(medicine.medicine)
let newQuantity = parseInt(medicineOne.quantity) + parseInt(medicine.quantity)
const filter = { _id: medicine.medicine };
const update = { quantity: newQuantity };
await Medicine.findByIdAndUpdate(filter, update);
let newmedi = {
name: medicine.name,
company: medicine.company,
medicine: medicineOne,
quantity: newQuantity,
pack_detail: medicine.pack_detail,
category: medicine.category,
batch: medicine.batch,
mrp: medicine.mrp,
rate: medicine.rate,
gst: medicine.gst,
totalAmount: medicine.totalAmount,
expiryDate: medicine.expiryDate
}
totalOrderAmount += medicine.totalAmount;
totalPaybleGst += medicine.gst * medicine.rate * medicine.quantity * 0.01;
medicines.push(newmedi);
})
const paidAmount = req.body.paidAmount
const supplierBeforeUpdate = await Supplier.findById(req.body.supplier);
const newOustanding = supplierBeforeUpdate.totalOutstanding + totalPaybleGst + totalOrderAmount - paidAmount;
const filter = { _id: req.body.supplier };
const update = { totalOutstanding: newOustanding };
await Supplier.findOneAndUpdate(filter, update);
const supplierAffterUpdate = await Supplier.findById(req.body.supplier);
const purchaseOrder = await PurchaseOrder.create({
supplier: supplierAffterUpdate,
createdBy: req.body.createdBy,
medicines: medicines,
paybleGst: totalPaybleGst,
totalAmount: totalOrderAmount,
grandTotal: totalPaybleGst + totalOrderAmount,
paidAmount: paidAmount
})
res.status(200).json({ success: true, purchaseOrder: purchaseOrder })
}
else {
res.status(400).json({ error: "This method is not allowed" })
}
}
export default connectDB(handler);
`
this is my purchaseOrder Schema
`
const mongoose = require('mongoose');
const { Schema, model, models } = mongoose;
const medicinePurchaseSchema = new Schema({
name: { type: String, required: true },
company: { type: String, required: true },
medicine: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Medicine'
},
quantity: { type: Number, required: true },
pack_detail: { type: String, required: true },
batch: { type: String, required: true },
mrp: { type: Number, required: true },
rate: { type: Number, required: true },
gst: { type: Number, required: true },
totalAmount: { type: Number, required: true },
expiryDate: { type: Date, required: true }
});
const purchaseOrderSchema = new Schema({
supplier: { type: Object, required: true},
createdBy: { type: String, required: true },
medicines: [medicinePurchaseSchema],
paybleGst: { type: Number, required: true },
totalAmount: { type: Number, required: true },
paidAmount: { type: Number, required: true },
grandTotal: { type: Number, required: true }
}, { timestamps: true })
const PurchaseOrder = models.PurchaseOrder || model('PurchaseOrder', purchaseOrderSchema);
export default PurchaseOrder;
`
`
const mongoose = require('mongoose');
const { Schema, model, models } = mongoose;
const medicineSchema = new Schema({
name: { type: String, required: true },
company: {type: String, required: true},
pack_detail: {type: Number, required: true},
quantity: { type: Number, required: true },
category: { type: String, required: true },
status: { type: String, required: true }
}, { timestamps: true });
const Medicine = models.Medicine || model('Medicine', medicineSchema);
export default Medicine;
`
this is my Medicine schema
but problem is I got **totalOrderAmount **and **totalPayableGst **is **0 **in newOutstanding calculation, i think my newOutstanding calculation line is executing before updating my these variable in medicines.each function.
How can I fix this, im trying since 2 days but i didn't get any solution.
anyone have any solution.
That forEach method call will execute synchronously and doesn't await any promises. The callbacks do have await, but those affect only the async function they occur in, not the forEach method.
Instead of using forEach, use map, so that you get back the array of promises (as the async callbacks return promises). To make sure those promises resolve to something useful, have those callbacks return the newmedi. With Promise.all you can then know when all those promises resolved, and get all the medicine values to store in the medicines array, and only continue with the rest of the function when that is done:
// Not forEach, but map, and await all returned promises
const medicines = await Promise.all(req.body.medicines.map(async medicine => {
/* ...rest of your callback code... */
return newmedi; // Don't push, but return it
}));

How can i create a module for a course website using mongoDB and node.js

/I want to create a module section for a course website for which I will need a lesson schema as well so How can I design lesson schema , module schema , and course schema so they
work just how they are needed to workCurrently I am doing this/
import mongoose from 'mongoose'
const LessonSchema = new mongoose.Schema({
title: String,
content: String,
resource_url: String
})
const ModuleSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
lessons: [LessonSchema]
})
export const Module = mongoose.model('Module', ModuleSchema);
const CourseSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: 'Name is required'
},
price: {
type: String,
trim: true,
required: true
},
image: {
data: Buffer,
contentType: String
},
intro: {
type: String,
required :true
},
description: {
type: String,
trim: true
},
category: {
type: String,
required: 'Category is required'
},
updated: Date,
created: {
type: Date,
default: Date.now
},
instructor: {type: mongoose.Schema.ObjectId, ref: 'User'},
published: {
type: Boolean,
default: false
},
modules: [ModuleSchema]
})
export default mongoose.model('Course', CourseSchema)
Above was the schema and this is logic
const newLesson = async (req, res) => {
try {
let lesson = req.body.lesson
let course = await Course.find({modules: {_id: req.params.moduleId}})
console.log(course)
} catch (err) {
return res.status(400).json({
error: errorHandler.getErrorMessage(err)
})
}
}
const newModule = async (req, res) => {
try {
let lesson = req.body.lesson
let result = await Course.findByIdAndUpdate(req.course._id, {$push: {modules: {name: req.body.name, lessons: lesson}}, updated: Date.now()}, {new: true})
.populate('instructor', '_id name')
.exec()
res.json(result)
} catch (err) {
return res.status(400).json({
error: errorHandler.getErrorMessage(err)
})
}
}
**I have been brainstorming this from a while and cant get through it do you know how can I shape the schema and logic so that I can push lessons in module and then module in course schema ? **

node.js moongose find populate cant access to array

I have this in my backend:
ad = await Ad.find({'company': companyId}).populate('creator');
And when i console.log(ad) i get this:
[
{
connections: [],
status: 1,
_id: 6047c711b1f8cf1c98b2227c,
title: "DOTA: Dragon's Blood | Teaser | Netflix",
company: 6047c6fab1f8cf1c98b2227a,
video: 'uploads\\videos\\7802d640-810a-11eb-83c2-57e23ae6d491.mp4',
creator: {
companies: [Array],
ads: [Array],
_id: 6047c6e7b1f8cf1c98b22279,
name: 'test test',
email: 'test#live.com',
image: 'uploads\\images\\5f3ea850-810a-11eb-83c2-57e23ae6d491.jpeg',
password: '',
__v: 3
},
__v: 0
},
{
connections: [ 6047c745b1f8cf1c98b22280, 6047c83bb1f8cf1c98b22286 ],
status: 1,
_id: 6047c72cb1f8cf1c98b2227f,
title: 'Diretide 2020',
company: 6047c6fab1f8cf1c98b2227a,
video: 'uploads\\videos\\87a97d60-810a-11eb-83c2-57e23ae6d491.mp4',
creator: {
companies: [Array],
ads: [Array],
_id: 6047c6e7b1f8cf1c98b22279,
name: 'test test',
email: 'test#live.com',
image: 'uploads\\images\\5f3ea850-810a-11eb-83c2-57e23ae6d491.jpeg',
password: '',
__v: 3
},
__v: 6
}
]
But when i try to console.log(ad.creator) or console.log(ad.creator.ads) im getting undefined error.. I need this becasue i want to pull some things from ad.creator.ads..
Do i miss something in my code?
I will try to be more specific i tried but i cant figure how to do this:
ad.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const adSchema = new Schema({
title: { type: String, required: true },
description: { type: String, required: true },
video: { type: String, required: true },
company: { type: mongoose.Types.ObjectId, required: true, ref: 'Company' },
creator: { type: mongoose.Types.ObjectId, required: true, ref: 'User' },
connections: [{type: mongoose.Schema.ObjectId, ref: 'User'}],
status: {type: Number, default: '1'}
});
module.exports = mongoose.model('Ad', adSchema);
So i need here when i delete this company to also pull all companies from user..
This is user.js
const mongoose = require('mongoose');
const uniqueValidator = require('mongoose-unique-validator');
const Schema = mongoose.Schema;
const userSchema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true, minlength: 6 },
image: { type: String, required: true },
companies: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Company' }],
ads: [{ type: mongoose.Types.ObjectId, required: true, ref: 'Ad' }]
});
userSchema.plugin(uniqueValidator);
module.exports = mongoose.model('User', userSchema);
process for deleting company in // i specified part with problem where need to pull ads from user for this:
const deleteCompany = async (req, res, next) => {
const companyId = req.params.cid;
let company;
let ad;
try {
company = await Company.findById(companyId).populate('creator');
ad = await Ad.find({'company': companyId}).populate('creator');
} catch (err) {
const error = new HttpError(
'backend_message13',
500
);
return next(error);
}
if (!company) {
const error = new HttpError('backend_message14', 404);
return next(error);
}
if (company.creator.id !== req.userData.userId) {
const error = new HttpError(
'backend_message15',
401
);
return next(error);
}
const imagePath = company.image;
try {
const sess = await mongoose.startSession();
sess.startTransaction();
await company.remove({ session: sess });
company.creator.companies.pull(company);
await company.creator.save({ session: sess });
// here is the path where is problem i also tried with ad[0]
ad.creator.pull(ad.creator.ads);
await ad.creator.save({ session: sess });
//
await Ad.deleteMany({'company': companyId});
await sess.commitTransaction();
} catch (err) {
const error = new HttpError(
err,
500
);
return next(error);
}
fs.unlink(imagePath, err => {
console.log(err);
});
ad.forEach(function (item) {
const videoPath = item.video;
const thumb = item.video.replace("uploads\\videos\\","uploads\\videos\\thumb\\").replace(".mp4", "_screenshot.jpeg");
fs.unlink(videoPath, err => {
console.log(err);
});
fs.unlink(thumb, err => {
console.log(err);
});
});
res.status(200).json({ message: 'backend_message17' });
};
Thanks for help :)
append lean() mean on populate and then see
ad = await Ad.find({'company': companyId}).populate('creator').lean();
The query Ad.find() returns an array - but your code tried to access it as an object:
ad = await Ad.find({'company': companyId}).populate('creator');
console.log(ad.creator)
ad.creator actually is an undefined
Use an index to access required array element:
ad = await Ad.find({'company': companyId}).populate('creator');
console.log(ad[0].creator)
Or switch to Ad.findOne()

TypeError: Order.find is not a function

I am building ecommerce website using MERN stack. And I am getting error while testing using Postman.
backend/controllers/user.js
const User = require("../models/user");
const Order = require("../models/order");
exports.userPurchaseList = (req, res) => {
Order.find({ user: req.profile._id })
.populate("user", "_id name")
.exec((err, order) => {
if (err) {
return res.status(400).json({
error: "No Order in this account",
});
}
return res.json(order);
});
};
backend/models/Order.js
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const ProductCartSchema = new mongoose.Schema({
product: {
type: ObjectId,
ref: "Product",
},
name: String,
count: Number,
price: Number,
});
const ProductCart = mongoose.model("ProductCart", ProductCartSchema);
const OrderSchema = new mongoose.Schema(
{
products: [ProductCartSchema],
transaction_id: {},
amount: { type: Number },
address: String,
status: {
type: String,
default: "Recieved",
enum: ["Cancelled", "Delivered", "Shipped", "Processing", "Recieved"],
},
updated: Date,
user: {
type: ObjectId,
ref: "User",
},
},
{ timestamps: true }
);
const Order = mongoose.model("Order", OrderSchema);
module.exports = { Order, ProductCart };
backend/models/User.js
const mongoose = require("mongoose");
const crypto = require("crypto");
const uuidv1 = require("uuid/v1");
var userSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
maxlength: 32,
trim: true,
},
lastname: {
type: String,
maxlength: 32,
trim: true,
// required: false,
},
email: {
type: String,
required: true,
trim: true,
unique: true,
},
userinfo: {
type: String,
trim: true,
},
encry_password: {
type: String,
required: true,
},
salt: String,
role: {
type: Number,
default: 0,
},
purchases: {
type: Array,
default: [],
},
},
{ timestamps: true }
);
module.exports = mongoose.model("User", userSchema);
backend/routes/user.js
router.get(
"/orders/user/:userId",
isSignedIn,
isAuthenticated,
userPurchaseList
);
Error:-
TypeError: Order.find is not a function
at exports.userPurchaseList (C:\Users\Rahul\MernBootcamp\projbackend\controllers\user.js:47:9)
TESTING this route using POSTMAN.
You have exported an object so in your backend/controllers/user.js
you could import it like so from destructuring from the object then the rest of your code would be okay
const {Order} = require("../models/order");
or
accessing it using the dot notation
when calling the find Function
//importing it at the top
const Order = require("../models/order");
exports.userPurchaseList = (req, res) => {
Order.Order.find({ user: req.profile._id })
.populate("user", "_id name")
.exec((err, order) => {
if (err) {
return res.status(400).json({
error: "No Order in this account",
});
}
return res.json(order);
});
};

posts.populate is not a function

I'm trying to populate my post's author fields (which is are object ids) with the corresponding author objects which are in a separate collection.
My controller code is as follows:
exports.readPosts = async (req, res) => {
try {
const posts = await Post.find({ board: req.params.board });
await posts.populate("author").execPopulate();
res.send(posts);
} catch (err) {
res.status(400).send(err.message);
}
};
I'm at a loss as to why this isn't working as I have very similar code in another controller method that is working just fine.
All help greatly appreciated.
Below is the relevant Model file:
const mongoose = require("mongoose");
const postSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
trim: true,
},
content: { type: String, required: true, trim: true },
comments: [
{
comment: {
type: String,
required: true,
trim: true,
},
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
date: {
type: Date,
default: Date.now(),
},
},
],
author: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
board: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "Board",
},
},
{ timestamps: true }
);
const Post = mongoose.model("Post", postSchema);
module.exports = Post;
posts is an array of models. populate must be called on a model. The preferred way to do this is at query time. It probably works on your other controller because you are using a findOne so it is returning the model, not the Array.
const posts = Post
.find({ board: req.params.board })
.populate('author')
.exec();

Categories