Can't Push data One to Many Relation (nodejs ,mongodb) - javascript

I am trying to insert data into MongoDB database but I get this error Cannot read property 'push' of undefined.
I can't understand what is the issue is here in my code. please help me with the solution. I am a Student and learning it.
here I am trying to push service into the category Model. for that, I have created a one to many relations between service and category. but I can't push the services into the category.
Schema design for category & Service =======
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const CategorySchema = new Schema({
name:{
type:String,
required:true
},
services:[
{
type:Schema.Types.ObjectId,
ref:'Service'
}
]
},{ timestamps:true })
const Category = mongoose.model("Cat", CategorySchema);
module.exports = Category;
service======
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const serviceSchema = new Schema({
title:{
type: 'String',
required: true
},
description:{
type: 'String',
required: true
},
image: {
type: 'String',
required: true
},
price: {
type: 'Number',
required: true
},
category: {
type:Schema.Types.ObjectId,
ref:'Cat'
}
})
const Service = mongoose.model("Service", serviceSchema);
module.exports = Service;
here is my service controller
postService:(req, res)=>{
const { title, price, description,category} = req.body;
const image = req.file.filename;
const service = new Service({
title,
price,
category,
description,
image,
});
service.save()
.then((service)=>{
const category = Category.findOneAndUpdate({_id: service.category})
category.services.push(service)
category.save()
console.log(category)
return res.redirect("/admin/services");
})
.catch((err) => {
console.log(err);
return res.redirect("/admin/services/create");
});
},

do like this:
postService: async(req, res)=>{
const { title, price, description,category} = req.body;
const image = req.file.filename;
const service = new Service({
title,
price,
category,
description,
image,
});
try {
await service.save()
let categoryModel = await Category.findById(category);//category should be an ObjectId
categoryModel.services.push(service)
await categoryModel.save()
return res.redirect("/admin/services");
} catch (err) {
console.log(err);
return res.redirect("/admin/services/create");
}
},

Related

exporting mongoose schema to be used for virtuals

I am trying to export my schema on a separate file to be used for setting virtuals:
const mongoose = require('mongoose');
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true,
toLowerCase: true
},
price: {
type: Number,
required: true,
min: 0
},
category: {
type: String,
enum: ['fruit', 'vegetable', 'dairy'],
toLowerCase: true
}
});
module.exports.Product = mongoose.model('Product', productSchema);
module.exports.productSchema = productSchema
and on a seperate file I want to create my instances using a virtual setter:
const mongoose = require('mongoose');
const { Product, productSchema } = require('./models/product');
mongoose.connect('mongodb://localhost:27017/farmStand', { useNewUrlParser: true })
.then(() => {
console.log('MONGO CONNECTION OPEN.')
}).catch(err => {
console.log('MONGO CONNECTION NOT OPEN!!!');
console.log(err);
});
productSchema.virtual('storeP').set(function (phrase) {
const input = phrase.split(' ');
console.log(input)
const name = input[0];
const price = parseInt(input[1]);
const category = input[2];
this.set({ name, price, category });
this.save();
});
let products = ['peach 1.99 fruit', 'strawberry 1.49 fruit', 'milk 1.99 dairy', 'honey 1.99 dairy', 'spinach 1.99 vegetable']
for (let product of products) {
const p = new Product({});
p.storeP = product
}
when I run the code there is no error but my data will not be stored on my database.
but if I copy my productSchema directly from the first file into the second one, it will be working fine! anything I missing when exporting?

How to push data with Mongoose to a nested array in MongoDB

I'm trying to push data to a nested array in mongodb. I'm using mongoose as well.
This is just mock code to see if i can get it working:
User model:
import mongoose from "mongoose";
const CoinSchema = new mongoose.Schema({
coinID: { type: String },
});
const CoinsSchema = new mongoose.Schema({
coin: [CoinSchema],
});
const WatchlistSchema = new mongoose.Schema({
watchlistName: { type: String },
coins: [CoinsSchema],
});
const NameSchema = new mongoose.Schema({
firstName: { type: String },
lastName: { type: String },
username: { type: String },
});
const UserSchema = new mongoose.Schema({
name: [NameSchema],
watchlists: [WatchlistSchema],
test: String,
});
const User = mongoose.model("User", UserSchema);
export default User;
route:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
const updatedUser = await User.findByIdAndUpdate(id, {
$push: { "watchlists[0].coins[0].coin": newCoin },
});
await updatedUser.save();
// console.dir(updatedUser, { depth: null });
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});
request.body // "coinID": "test"
I've tried a lot of different ways to push this data but still no luck. I still get 201 status codes in my terminal which indicates something has been pushed to the DB, but when I check nothing new is there.
Whats the correct way to target nested arrays and push data to them?
It's not perfect but you could get the user document, update the user's watchlist, and then save the updated watchlist like so:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
// get the user
let user = await User.findById(id);
// push the new coin to the User's watchlist
user.watchlists[0].coins[0].coin.push(newCoin);
//update the user document
const updatedUser = await User.findOneAndUpdate({ _id: id },
{
watchlists: user.watchlists,
},
{
new: true,
useFindAndModify: false
}
);
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});

Mongoose .Populate() returns empty array

I do not understand what the problem is.
And why each element from the 'tasks' array is null.
Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
tasks: [{type: Schema.Types.ObjectId, ref: 'Task'}]
}
);
const taskSchema = new Schema({
title: String
});
const User = mongoose.model('User', userSchema);
const Task = mongoose.model('Task', taskSchema);
// Add some default to DB
const task1 = new Task({
title: "Welcome! Here You Can:"
});
const task2 = new Task({
title: "ADD EDIT DELETE SHARE your TASKS "
});
const defaultTasks = [task1, task2];
When create new User I Add defaultTasks
const newUser = {
email: req.body.email,
password: req.body.password,
tasks: defaultTasks
};
Get Users Tasks
app.get('/tasks/', function(req, res){
const email = req.query.user;
User
.findOne({email: email})
.populate('tasks')
.exec()
.then(foundUser => {
console.log(foundUser);
const data = [];
Object.keys(foundUser.tasks).forEach(function(key) {
const val = foundUser.tasks[key];
data.push([val.title, val._id]);
});
res.send(data);
console.log('Data to send ' + data);
});
});
Before .Populate() console.log {
{ tasks: [ 5cf78ac1d08ee617fc89f7ed, 5cf78ac1d08ee617fc89f7ee ]
After { { tasks: [],
Please Help! All that I found did not solve my problem.
Maybe problem in defaultTasks. But i dont see it.
Your code doesn't save your task to DB, it just creates an object. So later when you populate User there are no tasks in DB to be found.
const task1 = await new Task({
title: "Welcome! Here You Can:"
}).save();
// or
const task1 = await Task.create({
title: "Welcome! Here You Can:"
});
P.s. of course you can deal with asynchronous calls the way you want.

How can I break this circular dependence between these two javascript modules?

How can I break the circular dependence between these two modules? Specifically, assignedDoctors: [Doctor.Schema] in the patient model, and assignedPatients: [Patient.Schema] in the doctor model.
/* Patient model */
const mongoose = require('mongoose')
const Notification = require('./notification')
const Appointment = require('./appointment')
const Doctor = require('./doctor')
const Medication = require('./medication')
const PatientSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
required: [true, "Missing user id."]
},
notifications: [Notification.schema],
appointments: [Appointment.schema],
assignedDoctors: [Doctor.schema],
medications: [Medication.schema]
});
const Patient = mongoose.model("Patient", PatientSchema);
module.exports = { Patient };
/* Doctor model */
const mongoose = require('mongoose')
const { Notification } = require('./notification')
const { Appointment } = require('./appointment')
const { Patient } = require('./patient')
const DoctorSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
required: [true, "Missing user id."]
},
specialty: String,
notifications: [Notification.schema],
assignedPatients: [Patient.schema],
appointments: [Appointment.schema],
});
const Doctor = mongoose.model("Doctor", DoctorSchema);
module.exports = { Doctor };
Someone suggested that I can solve it by introducing a third module file, but I am not sure what is it exactly I need to do. Can someone please show me?

How do I successfully populate a mongoose schema [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I have a Person model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const PersonSchema = new Schema({
name: String,
cars: [{
type: Schema.types.ObjectId,
ref: 'Cars'
}]
});
const Person = module.exports = mongoose.model('Person', PersonSchema);
and I have a Cars model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CarsSchema = new Schema({
color: String,
owner: {
type: Schema.Types.ObjectId,
ref: 'Person'
},
});
const Cars = module.exports = mongoose.model('Cars', CarsSchema);
How do I make sure that every time a car is added, it get listed in a particular person's car array?
Right now, I've done something like this:
const newPerson = new Person({
name: 'jared'
});
newPerson.save()
.then(person => {
console.log(person);
});
const newCar = new Car({
color: 'red'
});
newCar.save(function(err, car) {
if (err) {
console.log(err)
} else {
car.populate(
car, {
path: "owner"
},
function(err, car) {
if (err) {
console.log(err);
} else {
console.log(car);
}
});
}
});
the code works without errors, and the car gets properly printed to the terminal with the "jared" person document seen occupying the owner field, but the result isn't saved to MongoDB. Instead, when I check MongoDB, I just see the car with only the "jared" document _id occupying the owner field. Can anyone please tell me why that is?
You have to assign _id from the person to car owner.
let newPerson = new Person({
name: 'jared'
});
newPerson.save()
.then(person => {
console.log(person);
let newCar = new Car({
color: 'red',
owner: person._id
});
newCar.save(function(err, car) {
if (err) {
console.log(err)
} else {
car.populate(
car, {
path: "owner"
},
function(err, car) {
if (err) {
console.log(err);
} else {
console.log(car);
}
});
}
})
});

Categories