Search code examples
node.jsmongodbexpressmongoosemongoose-schema

Document is inserted twice into MongoDB when using Mongoose create method


I am having below schema in my API which gets details of username and the products he added to the cart.

const mongoose = require('mongoose');

mongoose.connect('mongodb connection').then(()=>{
console.log('DB connection is successfull');});

const AutoIncrement = require('mongoose-sequence')(mongoose);

const cartSchema = new mongoose.Schema({
cartId : {
    type : Number
},
username : {
    type : String
},
productsInCart : [{
    productId : {type : Number,required : true},
    productName : {type:String},
    quantity : {type:Number}
}],
statusOfCart : {
    type : String,
    default : 'Open'
}},{ timestamps: true });

cartSchema.plugin(AutoIncrement,{id : 'cart_seq',inc_field : 'cartId'});
let cartModel = mongoose.model('carts',cartSchema);
module.exports = cartModel;

As you can see in the above code I am also using the mongoose-sequence to make cartId as a auto-incremented field.

Now, I have a POST request which gets the below JSON in request body and adds it to the cart collection in the MongoDB using the create method.

{ "username":"admin", "productsInCart": [ { "productId":1, "productName":"Watch", "quantity":4 }, { "productId":2, "productName":"Phone", "quantity":5 } ] }

The code inside the Route Handler for the POST request in Express API would look something like this

let ctMod = new cartModel();
ctMod.username = req.body.username;
ctMod.productsInCart = req.body.productsInCart;
let insCartData = await cartModel.create(ctMod,{new:true});
if(insCartData.length > 0)
{
  return res.status(200).json({
       message : `New items got inserted into the cart with the ID : ${insCartData.cartId}`,
       data : insCartData
       });
 }

The above code inserts two entries into the collection like below instead of one

{ "statusOfCart": "Open", "productsInCart": [], "createdAt": "2021-01-04T15:25:35.188Z", "updatedAt": "2021-01-04T15:25:35.188Z", "cartId": 13, "__v": 0 }, { "statusOfCart": "Open", "productsInCart": [ { "_id": "5ff332a891aa170b60a21ea9", "productId": 1, "productName": "Watch", "quantity": 4 }, { "_id": "5ff332a891aa170b60a21eaa", "productId": 2, "productName": "Phone", "quantity": 5 } ], "username": "admin", "createdAt": "2021-01-04T15:25:35.210Z", "updatedAt": "2021-01-04T15:25:35.210Z", "cartId": 14, "__v": 0 }

can you help me understand why there is duplicate entries in my db?


Solution

  • I'm not sure why you are using cartModel.create(ctMod,{new:true}); inorder to create a new entry to your collection.

    You can simply do like this :

    let ctMod = new cartModel();
    ctMod.username = req.body.username;
    ctMod.productsInCart = req.body.productsInCart;
    
    try{
    let insCartData = await cartModel.save();
      return res.status(200).json({
          error:false,
           message : `New items got inserted into the cart with the ID : ${insCartData.cartId}`,
           
          data : insCartData
        
       });
     }
    catch(err){
    console.error("error inserting data", err);
    return res.status(500).json({error:true, message:"Something went wrong :("}).
    
    }
    
    

    UPDATE :

    Reason for the duplicate entry is that you are passing the {new:true} flag in the create API. It's used to return the updated document in the findOneAndUpdate method. But in create/save, the mongoose return the data by default. Hence the flag is not needed.If you omit the flag, duplicate entries can be prevented.

    Also, as you are using the create method to save the new entry, you need not create an instance of the cartModel. ie.,

    let ctMod = new cartModel();

    can be just

    let ctMod = {}

    Hope it helps!