Property 'push' of undefined - node.js

I am having some issue with express app when posting to a route, I am trying to pass some dishIds as shown below through the body of POSTMAN:
[
{"_id":"5f209e066e27a49e582b46bc"},
{"_id":"5f209e746e27a49e582b46be"}
]
I am trying to save Favorite dish and the schema is show below (favorite.js)(:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
require('mongoose-currency').loadType(mongoose);
const favoriteSchema = new Schema({
dishes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Dish'
}],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
},{
timestamps: true
})
var Favorites = mongoose.model('Favorite', favoriteSchema);
module.exports = Favorites;
I am trying to save user, dishId into Favourites model but I am getting an error that says " Cannot read property 'push' of undefined", Can anyone help me understand what Ia am getting wrong with POST Route below:
thank you in advance.
.post(cors.corsWithOptions, authenticate.verifyUser, (req, res, next) =>{
Favorites.create(req.body)
.then((favorite) => {
if( favorite != null) {
req.body.user = req.user._id // get the current user
favorite.dishes.push(req.body)
favorite.save()
.then((favorite) => {
Favorites.findById(favorite._id)
.populate('user') //populate the user
.then((favorite) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.json(favorite);
})
}, (err) => next(err))
}
else {
err = new Error('Dish ' + req.params.dishId + 'not found');
err.status = 404;
return next(err);
}
}, (err) => next(err))
.catch((err) => next(err));
})

Related

.populate() returning empty array?

I'm working on project and I am trying to get the users reviews to display on the page. However whenever I run my application it returns an empty array and I'm not sure why, I have no issue with the getReviews function as it returns everything correctly, but getUserReviews just returns an empty array with no error. I've tried multiple methods and just can't seem to get it
Review Model
const mongoose = require("mongoose");
const Review = mongoose.model(
"Review",
new mongoose.Schema({
movieId: String,
reviewId: String,
content: String,
sentimentScore: String,
author: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
],
reponseTo: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
]
})
);
module.exports = Review;
User Model
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
roles: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Role"
}
]
})
);
module.exports = User;
Review Routes
const express = require('express');
const router = express.Router();
const {authJwt} = require("../middlewares");
const Review = require("../models/review.model")
router.use(function(req, res, next) {
res.header(
"Access-Control-Allow-Headers",
"x-access-token, Origin, Content-Type, Accept"
);
next();
});
router.post("/addReview", [authJwt.verifyToken], (req, res) => {
const review = new Review(req.body)
review.save((err, review) => {
if(err) return res.json({success:false, err})
Review.find({'_id': review._id})
.populate('author')
.exec((err, result) => {
if(err) return res.json({success: false, err})
return res.status(200).json({success: true, result})
})
})
})
router.post("/getReviews", [authJwt.verifyToken], (req, res) => {
Review.find({"movieId": req.body.data})
// console.log("ID ", req.body.data)
.populate('author')
.exec((err, reviews) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, reviews})
})
})
router.post("/getUserReviews", [authJwt.verifyToken], (req, res) => {
Review.find({"userId": req.body.data})
.populate({
path: 'author.user',
model: 'Review'})
.exec((err, reviews) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, reviews})
})
})
You try to query Review collection with userId field, and Review collection does not have userId field in its model definition.
Maybe you wanted to query author array? In that case, try this:
router.post("/getUserReviews", [authJwt.verifyToken], (req, res) => {
Review.find({ author: req.body.data })
.populate('author')
.exec((err, reviews) => {
if(err) return res.status(400).send(err)
res.status(200).json({success: true, reviews})
})
})

How to Delete document and sub documents referenced from others collections - MongoDB Mongoose

I have this collection Cart (cart schema) to delete and it is referenced with 2 other schemes, Meal and Customer (owner user, its schema is: User Schema).
How can I delete the cart by passing as req.params.id the user's id from the HTTP request?
Cart Schema
const mongoose = require('mongoose');
const idValidator = require('mongoose-id-validator');
const Schema = mongoose.Schema;
const cartItemSchema = new Schema ({
quantity: { type: Number, required: true },
itemId: { type: mongoose.Types.ObjectId, required: true, ref: 'Meal' }
});
const cartSchema = new Schema ({
cartItems : [
cartItemSchema
],
customer: { type: mongoose.Types.ObjectId, required: true, ref: 'User'}
});
cartSchema.plugin(idValidator);
module.exports = mongoose.model('Cart', cartSchema);
I created a function to delete the document, but it doesn't work, it returns the message: 'Deleted cart.', but isn't true, the document remains in collection.
const deleteCartByUserId = async (req, res, next) => {
const userId = req.params.uid;
let cart;
try {
cart = await Cart.find({ customer: userId });
} catch(err) {
const error = new HttpError('Something went wrong, could not delete cart.', 500);
return next(error);
}
if(!cart) {
const error = new HttpError('Could not find cart for this user id.', 404);
return next(error);
}
try {
Cart.deleteOne({ customer: userId });
} catch(err) {
console.log(err);
const error = new HttpError('Something went wrong, could not delete cart.', 500);
return next(error);
}
res.status(200).json({ message: 'Deleted cart.' });
};
So the porblem was that you missed an await before delete one function call.
Also I've changed some of youre code to make it cleaner:
const functionHandler = fn =>
(req, res, next) =>
Promise
.resolve(fn(req, res, next))
.catch(next);
const deleteCartByUserId = functionHandler(async (req, res) => {
const { params: { uid: userId } } = req;
const cart = await Cart.findOneAndDelete({ customer: userId })
if(!cart) {
throw new HttpError('Could not find cart for this user id.', 404);
}
res.status(200).json({ message: 'Deleted cart.' });
});
In your error handler middleware you can check for error type and if it's not HttpError use internal server error.

Get data from different model nodejs mongodb express js

I have two model files Bank Deposits and Sub account details. From Sub account details I want to get current balance to Bank deposits . I want to do this in mongodb and node js. I am currently aggreagate lookup operation but it is showing the array as empty.
BankdepositModel.js
var mongoose = require("mongoose");
var BankDepositsSchema = new mongoose.Schema(
{
source_sub_account: Array,
amount: Number,
cheque_notes: Number,
to_bank_account: Array,
amount_in_words: String,
bank_Ref_no: String
},
{
timestamps: true
}
);
module.exports = mongoose.model("BankDeposits", BankDepositsSchema);
Subaccountdetailsmodel.js
var mongoose = require("mongoose");
var SubAccountDetailsSchema = new mongoose.Schema(
{
sub_account_name: String,
current_balance: Number,
account: Array
},
{
timestamps: true
}
);
module.exports = mongoose.model("SubAccountDetails", SubAccountDetailsSchema);
Controller.js
var BankDeposits = require("../model/bankdepositmodel");
var SubAccountDetails = require("../model/subaccountsmodel.js");
exports.create1 = (req, res) => {
var BankDeposit = new BankDeposits({
source_sub_account: req.body.source_sub_account,
amount: req.body.amount,
cheque_notes: req.body.cheque_notes,
to_bank_account: req.body.to_bank_account,
amount_in_words: req.body.amount_in_words,
bank_ref_no: req.body.bank_ref_no
});
BankDeposit.save()
.then(data1 => {
res.send(data1);
})
.catch(err => {
res.status(500).send({
message: err.message
});
});
};
//BankDeposit get
exports.find1 = (req, res) => {
BankDeposits.aggregate([
{
$lookup: {
from: "SubAccountDetails",
localField: "current_balance",
foreignField: "current_balance",
as: "balance"
}
}
])
.then(appdata => {
res.status(200).send(appdata); //On successful fetch, server responds with status 200
})
.catch(err => {
res.status(400).send(err); //On error, server responds with status 400
});
};
//sub account details post
exports.createSubAccountDetail = (req, res) => {
var SubAccountDetail = new SubAccountDetails({
sub_account_name: req.body.sub_account_name,
current_balance: req.body.current_balance,
account: req.body.account
});
SubAccountDetail.save()
.then(SubAccountDetail => {
res.send(SubAccountDetail);
})
.catch(err => {
res.status(500).send({
message: err.message
});
});
};
//sub account details get
exports.SubAccountDetail = (req, res) => {
SubAccountDetails.find()
.then(SubAccountDetails => {
res.send(SubAccountDetails);
})
.catch(err => {
res.status(500).send({
message: err.message || "Some error occurred while retrieving regs."
});
});
};
You can get it like this
BankDeposits.aggregate([
{
$lookup: {
from: "SubAccountDetails",
localField: "source_sub_account",
foreignField: "sub_account_name",
as: "sub_acount"
}
}
])
Now you will get your complete sub_account object in sub_account property of returned data, current_balance will be in same
This is assuming that sub_account_name in SubAccountDetails & source_sub_account in BankDeposits are same

How can I populate an existing Mongo Document when creating another?

I am using mongoose and express to build an API for storing technology work tickets. I have a field in my Ticket model that references a User id and an array field in my User model that references all the Tickets (by ID) that are owned by that user.
When I create a new Ticket (using HTTP post method), I want my database to automatically add that ticket's id to the tickets field of its assigned user (like a SQL Join). However, I can't get it to work.
I've tried updating my user model inside the /tickets POST request in my router, but can't wrap my head around how to actually make it work.
Here is my code:
// Ticket Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Promise = require('bluebird');
const ObjectId = mongoose.Schema.Types.ObjectId;
const User = require('./user');
Promise.promisifyAll(mongoose);
const TicketSchema = new Schema({
open: {type: Date, required: true},
close: Date,
description: {type: String, required: true},
done: Boolean,
status: String,
repairType: {type: String, required: true},
ticketOwner: {type: ObjectId, ref: 'User', required: true}
});
const Ticket = mongoose.model('Ticket', TicketSchema, 'tickets');
module.exports = Ticket;
// User Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Promise = require('bluebird');
const ObjectId = mongoose.Schema.Types.ObjectId;
const Ticket = require('./ticket');
Promise.promisifyAll(mongoose);
const UserSchema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
email: {type: String, required: true},
tickets: [{type: ObjectId, ref: 'Ticket'}]
});
const User = mongoose.model('User', UserSchema, 'users');
module.exports = User;
// Tickets Route
const express = require('express');
const router = express.Router();
const Ticket = require('../models/ticket');
router.route('/')
// READ all tickets.
.get(function(req, res, next) {
Ticket.findAsync({})
.then(function(tickets) {
res.json(tickets);
})
.catch(next)
.error(console.error);
})
// CREATE new ticket.
.post(function(req, res, next) {
let ticket = new Ticket();
let prop;
for (prop in req.body) {
ticket[prop] = req.body[prop];
}
ticket.saveAsync()
.then(function(ticket) {
console.log('success');
res.json({'status': 'success', 'ticket': ticket});
})
.catch(function(e) {
console.log('fail');
res.json({'status': 'error', 'error': e});
})
.error(console.error);
});
router.route('/:id')
// READ a single Ticket by ID
.get(function(req, res, next) {
Ticket.findOne({_id: req.params.id}, {})
.populate('ticketOwner')
.exec(function (e, ticket) {
if (e) return console.error(e);
res.json(ticket);
})
})
// UPDATE a Ticket
.put(function(req, res, next) {
let ticket = {};
let prop;
for (prop in req.body) {
ticket[prop] = req.body[prop];
}
Ticket.updateAsync({_id: req.params.id}, ticket)
.then(function(updatedTicket) {
return res.json({'status': 'success', 'ticket': updatedTicket})
})
.catch(function(e) {
return res.status(400).json({'status': 'fail', 'error': e});
});
})
// DELETE a Ticket
.delete(function(req, res, next) {
Ticket.findByIdAndRemoveAsync(req.params.id)
.then(function(deletedTicket) {
res.json({'status': 'success', 'ticket': deletedTicket});
})
.catch(function(e) {
res.status(400).json({'status': 'fail', 'error': e})
});
});
module.exports = router;
// Users Route
const express = require('express');
const router = express.Router();
const User = require('../models/user');
router.route('/')
// READ all users.
.get(function(req, res, next) {
User.findAsync({})
.then(function(users) {
res.json(users);
})
.catch(next)
.error(console.error);
})
// CREATE new user.
.post(function(req, res, next) {
let user = new User();
let prop;
for (prop in req.body) {
user[prop] = req.body[prop];
}
user.saveAsync()
.then(function(user) {
console.log('success');
res.json({'status': 'success', 'user': user});
})
.catch(function(e) {
console.log('fail');
res.json({'status': 'error', 'error': e});
})
.error(console.error);
});
router.route('/:id')
// READ a single User by ID
.get(function(req, res, next) {
User.findOne({_id: req.params.id}, {})
.populate('tickets')
.exec(function (e, user) {
if (e) return console.error(e);
res.json(user);
})
})
// UPDATE a User
.put(function(req, res, next) {
let user = {};
let prop;
for (prop in req.body) {
user[prop] = req.body[prop];
}
User.updateAsync({_id: req.params.id}, user)
.then(function(updatedUser) {
return res.json({'status': 'success', 'user': updatedUser})
})
.catch(function(e) {
return res.status(400).json({'status': 'fail', 'error': e});
});
})
// DELETE a User
.delete(function(req, res, next) {
User.findByIdAndRemoveAsync(req.params.id)
.then(function(deletedUser) {
res.json({'status': 'success', 'user': deletedUser});
})
.catch(function(e) {
res.status(400).json({'status': 'fail', 'error': e})
});
});
module.exports = router;

How to make a record in mongodb refrence model

I working on Mongoose and Express project where by I have 3 models: User, Album and Purchase. The purchase model references the user and album. I am creating a POST endpoint where by I can make a purchase and then retrieve the data as well as the user and album relations which should be populated with their data, but I am stuck.
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
// TODO: Define Schema
name: {
type: String,
required: true
}
})
var User = mongoose.model('User', userSchema)
var albumSchema = mongoose.Schema({
// TODO: Define Schema
title: {
type: String,
required: true
},
performer: {
type: String,
required: true
},
cost: {
type: Number,
required: true
}
})
var Album = mongoose.model('Album', albumSchema);
var puchaseSchema = mongoose.Schema({
// TODO: Define Schema
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Album'
},
album: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
})
var Purchase = mongoose.model('Purchase', puchaseSchema);
app.use(bodyParser.json());
app.listen(3000);
// TODO: GET /albums
app.get('/albums', (req,res) => {
Album.find()
.then((response) => {
res.json({data: response})
})
.catch(err => {
res.json({error: err})
})
})
// TODO: GET /albums/:id
app.get('/albums/:id', (req,res) => {
Album.findById(req.params.id)
.then(response => {
res.json({data: response})
.catch(err => {
res.json({Error: err})
})
})
})
// TODO: POST /albums
app.post('/albums', (req,res) => {
const newPost = Album({
title: req.body.title,
performer: req.body.performer,
cost: req.body.cost
})
newPost.save(err => {
if(err)
res.json({error: err})
})
.then(data => {
res.json({data: data})
})
})
// TODO: PUT /albums/:id
app.put('/albums/:id', (req,res) => {
Album.findByIdAndUpdate(req.params.id, req.body, {new: true},
(err, album) =>{
if(err) return res.status(500).send(err)
return res.json({data: album})
})
})
// TODO: DELETE /albums/:id
app.delete('/albums/:id', (req,res) => {
const id = req.params.id
Album.findById(id)
.then(docs => {
docs.remove()
res.status(204)
.json({data:docs})
})
})
// TODO: POST /purchases
app.post('/purchases', (req,res) => {
})```
This might help you. Look into mongoose's populate method.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.findById(purchase.id).populate('user').populate('album').then((purchaseData) => {
return res.json({purchaseData});
}).catch(e => {
console.log(e);
});
}).catch(e => {
console.log(e);
});
})
Here's an alternative for populating after saving the document.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.populate(purchase, [{path: 'user'}, {path: 'album'}], (err, data) => {
if(err) {
return res.json(e);
}
return res.json(data);
});
}).catch(e => {
console.log(e);
});
}
)
As mentioned here: https://mongoosejs.com/docs/api.html#model_Model.populate

Resources