Rahul jhawar
Rahul jhawar

Reputation: 237

Mongoose model schema referencing not working

Basically I have 3 mongoose models(user,product,cart).I have tried referencing cart model with user model.I've the used populate method in mongoose to populate the referenced property in the model.But it is not working and I'm getting an empty cart array after adding a product to the cart like this on consoling.

  {
    "_id": "5a0b2dcf726753258002273d",
    "password": "12345",
    "securityQuestion": "What is your Nick Name?",
    "securityAnswer": "rj1",
    "__v": 0,
    "cart": [], // empty cart here
    "mobileNumber": 1234567890,
    "email": "rahul@gmail.com",
    "lastName": "jhawar",
    "firstName": "rahul",
    "userName": "rj"
  }

I also wanted to know whether my referencing of models are done correctly(I mean the relationship).

I'm new to this concept.Please help me out.

 //Cart.js
  var mongoose = require('mongoose');
  var Schema = mongoose.Schema;
  var cartSchema = new Schema({

productName         : {type:String,default:''},
productCategory     : {type:String,default:''},
productDescription  : {type:String,default:''},
productPrice        : {type:String,default:''},
sellerName          : {type:String,default:''},

});

module.exports=mongoose.model('Cart',cartSchema);
//User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({

userName            : {type:String,default:'',required:true},
firstName           : {type:String,default:''},
lastName            : {type:String,default:''},
email               : {type:String,default:''},
mobileNumber        : {type:Number,default:''},
password            : {type:String},
securityQuestion    : {type:String},
securityAnswer      : {type:String},
cart                : [{
                          type: Schema.Types.ObjectId, 
                          ref:'Cart' 
                      }]


 });
  module.exports=mongoose.model('User',userSchema);



 ///Routes///
 const cartRouter  = express.Router();
 const cartModel = mongoose.model('Cart');
 const userModel = mongoose.model('User');
 const productModel = mongoose.model('Product');


  cartRouter.get('/addtocart/:id',auth.checkLogin,(req,res)=>{
       productModel.findOne({'_id':req.params.id},(err,foundProduct)=>{
        if(!err){
             const newCartProduct = new cartModel({

                productName         : foundProduct.productName,
                productCategory     : foundProduct.productCategory,
                productDescription  : foundProduct.productDescription,
                productPrice        : foundProduct.productPrice,
                sellerName          : foundProduct.sellerName

                });

             newCartProduct.save((err)=>{
                if(!err){




      userModel.findOne({'_id':req.session.user._id}).populate('cart')
      . exec((err,cartproduct)=>{
                    console.log(JSON.stringify(cartproduct, null, "\t"));
                });
                console.log('New Product added to cart');
                res.redirect('/users/cart_products');
            }
            });
         });
       });

Upvotes: 2

Views: 1526

Answers (1)

Robert Moskal
Robert Moskal

Reputation: 22553

You've correctly set up the relationship between the user and the cart models in that the user potentially holds a reference to a number of cart models.

However, when you save the cart, you aren't actually updating the cart array/property of the user. You have to both save your newCartProduct and you also have to push the resultant id into the cart array and then save your user model. If you don't do this the populate method isn't going to work, since it has nothing to populate.

Here's an example of how you might use findByIdandUpdate to update the user with the new cart item.

cartRouter.get('/addtocart/:id',auth.checkLogin,(req,res)=>{
       productModel.findOne({'_id':req.params.id},(err,foundProduct)=>{
        if(!err){
             const newCartProduct = new cartModel({

                productName         : foundProduct.productName,
                productCategory     : foundProduct.productCategory,
                productDescription  : foundProduct.productDescription,
                productPrice        : foundProduct.productPrice,
                sellerName          : foundProduct.sellerName

                });

             newCartProduct.save((err, o)=>{
                if(!err){
                userModel.findByIdAndUpdate(req.session.user._id,
                {$push: {"cart": o._id}},
                {safe: true, new : true})
                .populate('cart')
                .exec((err, model) => {
                 console.log(model); //This will have the cart array filled in
             });

         });
       });

Other choices would be either to reverse the relationship, to hang the reference to the user from the cart, or to use an embedded subdocument:

cart: [Cart]

If you never need to access cart entries outside of the context of a single user (if you never need aggregate information across users), then it's probably the right thing to do.

Your approach maybe right for your use cases, but then you have to manually maintain both sides of the relationship when items are added and removed from the cart.

Upvotes: 1

Related Questions