Relationship mongoose - javascript

I'm have two schemas where one depends of the other to save.
const OrderSchema = new moongose.Schema({
product: {
type: moongose.Schema.Types.ObjectId,
ref: 'Product',
required: true
},
quantity: {
type: Number,
required: true,
default: 1,
},
total_price: {
type: Number,
}
})
OrderSchema.pre('save', async function(next) {
this.total_price = product.price * quantity
next()
})
const Order = moongose.model('Order', OrderSchema)
And the other:
const ProductSchema = new moongose.Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String
},
photo: {
data: Buffer,
contentType: String
}
})
const Product = moongose.model('Product', ProductSchema)
But when I try save one Order with one Product exiting in data base:
{
"product":"5cae6ff5d478882ed8725911",
"quantity":3
}
Show error: Error: ReferenceError: product is not defined
This is my controller to save a new Order:
router.post('/register', async (req, res) => {
try {
const order = await Order.create(req.body)
return res.send({ order })
}
catch (error) {
console.error('Error:', error)
}
})

I usually use
    idproduct: {
         type: moongose.Schema.ObjectId,
         required: true
     },
This way the post works correctly

LOL, I found the ERROR:
OrderSchema.pre('save', async function(next) {
this.total_price = product.price * quantity
next()
})
I forgot to use 'THIS', correct:
OrderSchema.pre('save', async function(next) {
this.total_price = this.product.price * this.quantity
next()
})
Hehehe, sorry guys...

Related

Nested schema with map field is not working with mongoose and node js

I’m pretty new to using Mongoose and can’t seem to find a fix. I have two schema’s; postSchema, commentSchema. The first one is for a post and the second is for comments that are stored within the post. Both schema’s have a map field to store likes. The post likes field’s setter and getter work when I try to update but when I try to do the same for the comments it gives me an error that the set or get is not a function. When I check if the likes are an instance of a map, the post likes will return true, while the comments like will return false. If anyone could help or direct me in the right direction it would be greatly appreciated.
Here is the code that I'm working with. When I create a comment to add to a post, the comment.likes checks as a Map. After I update the post I make a call to get all the post's and I rechecked that the comment.likes is a Map, but now it turns out false.
import mongoose from 'mongoose';
const postSchema = mongoose.Schema(
{
userId: {
type: String,
required: true,
},
userName: {
type: String,
required: true,
},
picturePath: {
type: String,
default: '',
},
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
likes: {
type: Map,
of: Boolean,
default: new Map(),
},
comments: {
type: Array,
default: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }],
},
},
{ timestamps: true }
);
const Post = mongoose.model('Post', postSchema);
export default Post;
import mongoose from 'mongoose';
const commentSchema = mongoose.Schema(
{
postId: {
type: String,
required: true,
},
userId: {
type: String,
required: true,
},
userName: {
type: String,
required: true,
},
picturePath: {
type: String,
default: '',
},
description: {
type: String,
required: true,
},
likes: {
type: Map,
of: Boolean,
default: new Map(),
},
},
{ timestamps: true }
);
const Comment = mongoose.model('Comment', commentSchema);
export default Comment;
export const addComment = async (req, res) => {
try {
const { id } = req.params;
const { userId, picturePath, description } = req.body;
const user = await User.findById(userId);
const newComment = new Comment({
id,
userId,
userName: user.userName,
picturePath,
//likes: {},
description,
});
newComment.set('likes', new Map());
console.log(newComment.likes instanceof Map);
const upDatedPost = await Post.findByIdAndUpdate(
id,
{ $push: { comments: newComment } },
{ new: true }
);
const allPost = await Post.find();
console.log(allPost[0].comments[2].likes instanceof Map);
res.status(200).json(allPost);
} catch (err) {
console.log('err');
res.status(404).json({ message: err.message });
}
};
This works for the post.likes.
export const likePost = async (req, res) => {
try {
const { id } = req.params;
const { userId } = req.body;
const post = await Post.findById(id);
const isLiked = post.likes.get(userId);
if (isLiked) {
post.likes.delete(userId);
} else {
post.likes.set(userId, true);
}
const upDatedPost = await Post.findByIdAndUpdate(
id,
{ likes: post.likes },
{ new: true }
);
res.status(200).json(upDatedPost);
} catch (err) {
res.status(404).json({ message: err.message });
}
};
This doesn’t work. When I check if element.likes is an instanceOf Map it gives back false, but for post.likes it returns true. Updated with the console.log's.
export const likeComment = async (req, res) => {
try {
const { id } = req.params;
const { postId, userId } = req.body;
let post = await Post.findById(postId);
let comments = post.comments;
console.log('comments: ', comments);
console.log('likes: ', comments[0].likes);
console.log(
'Is likes an instanceof Map: ',
post.comments[0].likes instanceof Map
);
//comments[0].likes.set(userId, true);
//post.comments[0].set('likes', new Map());
//console.log(comments[6].likes);
// comments.forEach((element) => {
// if (element._id.toString() === id) {
// element.likes.set(userId, true);
// }
// });
res.status(200).json(post);
} catch (err) {
res.status(404).json({ message: err.message });
}
};
Here is the output fro the console.log's.
comments: [
{
userId: '63dc0274bd8c03b1e417cfc4',
userName: 'dummyUserThree',
picturePath: '',
description: 'Likes still not working',
_id: new ObjectId("63e13f26603a052fc8f16b09"),
likes: {}
}
]
likes: {}
Is likes an instanceof Map: false

CastError: Cast to [undefined] failed for value "[]" (type string) at path "comments.undefined"

I'm quite new to node and mongoose. I'm trying to do a project using them, but i'm running into an error while trying to populate. The comment is saved to the Comment schema perfectly, but throws an error when i reference it Organization Schema.Please advise me on what i'm doing wrong. Any form of assistance will be appreciated.
// Post route for comment(on the Organization's profile page)
router.post('/comment/:id', ensureAuthenticated,(req, res) =>{
let id = req.params.id;
console.log(mongoose.Types.ObjectId.isValid(id))
const commentObject = new Comment({
sender: 'Fred kimani',
commentBody: req.body.commentBody
})
console.log(commentObject);
commentObject.save((err, result) =>{
if(err){console.log(err)}
else{
Organization.findByIdAndUpdate(id, {$push: {comments: result}}, {upsert: true}, (err, organization) =>{
if(err){console.log(err)}
else{
console.log('======Comments====')
}
})
res.redirect('/users/organizationprofilepage/:id')
}
})
});
//Organization Schema
const mongoose = require('mongoose');
const OrganizationSchema = new mongoose.Schema({
organization_name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
category: {
type: String,
required: true
},
isApproved: {
type: Boolean,
default: false
},
image:{
type:String,
required:true
},
description: {
type: String,
required: true,
},
comments: [{
type: mongoose.Types.ObjectId,
ref: 'Comment'
}],
},
//{ typeKey: '$type' }
);
OrganizationSchema.statics.getOrganizations = async function () {
try {
const organizations = await this.find();
return organizations;
} catch (error) {
throw error;
}
}
//defines the layout of the db schema
const Organization = mongoose.model('0rganization', OrganizationSchema);
module.exports = Organization;
//Comment schema
const mongoose = require('mongoose');
const CommentSchema = mongoose.Schema({
sender: {
type: String,
},
commentBody: {
type: String,
required: false,
},
date: {
type: Date,
default: Date.now
},
})
CommentSchema.statics.getComments= async function () {
try {
const comments = await this.find();
return comments ;
} catch (error) {
throw error;
}
}
const Comment= mongoose.model('Comment', CommentSchema);
module.exports = Comment;
Try to change the comments type to mongoose.Schema.Types.ObjectId:
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment',
},
],
Try to push the new commend _id into the Organization object after its creation, not the whole object:
commentObject.save((err, result) => {
if (err) {
console.log(err);
} else {
Organization.findByIdAndUpdate(
id,
{ $push: { comments: result._id } }, // <- Change this line
{ upsert: true },
(err, organization) => { }
);
...
}
});
If you just updated the schema you will need to make sure all of the comments are following the new form you created, when you save it will attempt to validate them, that is why an updateOne will work but not await save()

How do I add new object or push into array Mongodb Compass NodeJS Express (update is not a function)?

At this moment I try to find the query which works in this case, but then want to update the object. So I want to check if review object exist and if not then create that key name first and then push that object into an array. Else push into that in existing object of array.
Default object looks like (without review object):
const mongoose = require('mongoose');
const musicSchema = mongoose.Schema({
id: {
type: Number,
required: true
},
artist: {
type: String,
required: true
},
title: {
type: String,
required: true
},
release_year: {
type: Number,
required: true
},
genre_id: {
type: Number,
required: true
},
image_url: {
type: String,
required: true
},
reviews: [{
id: {
type: Number,
required: true
},
locale: {
type: String,
required: true
},
rating: {
type: Number,
required: true
},
comment: {
type: String,
required: true
}
}]
});
const Music = mongoose.model("Music", musicSchema); // now we have to create our model
console.log;
module.exports = Music; // export our created model
app.post('/addReview/:id', async (req, res) => {
let idNumber = parseInt(req.params.id); // 501437
let reviewObject = req.body; // {id: "501437", locale: "nl", rating: 3, text: "helello"}
try {
const music = client.db('database').collection('music');
const query = { id: idNumber };
const musicSong = await music.findOne(query);
await musicSong.update({ $push: { reviews: reviewObject } }); // error comes from here
} catch (err) {
console.log(err);
}
});
check if reviews field is not exists then initialise it to blank array
push object to reviews
save() to save main document
app.post('/addReview/:id', async (req, res) => {
let idNumber = parseInt(req.params.id); // 501437
let reviewObject = req.body; // {id: "501437", locale: "nl", rating: 3, text: "helello"}
try {
const music = client.db('database').collection('music');
const query = { id: idNumber };
let musicSong = await music.findOne(query);
if (!Array.isArray(musicSong.reviews)) {
musicSong.reviews = [];
}
musicSong.reviews.push(reviewObject);
music.save();
} catch (err) {
console.log(err);
}
});
Second option using updateOne():
It does not require to find, check and save operations if you use update methods,
app.post('/addReview/:id', async (req, res) => {
const query = { id: parseInt(req.params.id) };
let reviewObject = req.body;
try {
const music = client.db('database').collection('music');
await music.updateOne(query, { $push: { reviews: reviewObject } });
} catch (err) {
console.log(err);
}
});

How to update Data in MongoDB when checked body is selected

How can I update data in MongoDB when I check the checkbox without submitting any form.
My Schema
const userSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
},
todos: [
{
task: {
type: String,
trim: true,
required: 'Please Enter your Task',
},
dueDate: {
type: Date,
default: new Date(+new Date() + 3 * 24 * 60 * 60 * 1000),
},
dueTime: String,
done: {
type: Boolean,
default: false,
},
},
],
});
I want to update the done element which is in todos array.
I tried to do this.
Main Client Side JavaScript
$(document).ready(function () {
$('.todo--checkbox').change(function () {
let isChecked;
if (this.checked) {
isChecked = true;
$.ajax({
url: '/todo/' + this.value,
type: 'PUT',
data: { done: true },
});
} else {
isChecked = false;
$.ajax({
url: '/todo/' + this.value,
type: 'PUT',
data: { done: false },
});
}
});
});
In the front-end I have set the value of the checkbox to the _id of the object.
/routes/index.js here I am handling my routes
router.put('/todo/:id', todoControllers.checkStatus);
And Finally I am handling that contorller in my todoCOntroller.js
exports.checkStatus = async (req, res) => {
try {
const user = await User.aggregate([
{ $unwind: '$todos' },
{ $match: { 'todos._id': req.params.id } },
]);
// res.json(user);
console.log(user);
} catch (err) {
console.log('error: ', err);
}
};
But I am not getting any user in my console.
Please tell me where I am wrong.
You don't need to use aggregate. You can do it by using $elemMatch
const user = await User.find({
todos: { $elemMatch: { _id: req.params.id } },
});
For more information read the docs

How can I solve this referencing Problem in mongoose/Node JS

I have route and model for User and then another for Loan. I'm trying to reference the user inside the Loan route but I get this error anytime I test on PostMan:
TypeError: Cannot read property '_id' of undefined
at C:\Users\Micho\Documents\GBENGA\BE\src\routes\loans\index.js:38:47
Loan Model code is:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const loanSchema = new Schema({
customerName: {
type: String,
required: true
},
gender: {
type: String
},
address: {
city: String,
state: String,
},
amount: {
type: Number
},
loanTenure: {
type: Number
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
loanStatus: {
type: String,
default: "created"
}
}, {
timestamps: true
})
My route is this:
router.post("/", async (req, res) => {
try {
let loan = await new Loan({...req.body});
loan.save();
await User.findByIdAndUpdate(req.user._id, { $push: { loans: loan._id } })
console.log(req.user)
loan = await Loan.findById(loan._id).populate("user");
res.send(loan);
} catch (error) {
console.log(error)
res.status(500).send(error);
}
});
Kindly help. Thanks

Categories