bltzrrr
bltzrrr

Reputation: 809

Mongoose: updating array in document not working

I'm trying to update an array in document by adding object if it doesn't exist, and replacing the object in array otherwise. But nothing ($push, $addToSet) except the $set parameter does anything, and $set works as expected - overwrites the whole array. My mongoose schema:

var cartSchema = mongoose.Schema({
   mail: String,
   items: Array
});

The post request handler:

app.post('/addToCart', function(req, res) {
var request = req.body;
Cart.findOneAndUpdate({
        "mail": request.mail
    }, {
        $addToSet: {
            "items": request.item
        }
    }, {
        upsert: true
    },
    function(err, result) {
        console.log(result);
    }
);
    res.send(true);
});

The data that I'm sending from the client:

{  
"mail":"[email protected]",
"item":{  
      "_id":"59da78db7e9e0433280578ec",
      "manufacturer":"Schecter",
      "referenceNo":"Daemon-412",
      "type":"Gitare",
      "image":"images/ba9727909d6c3c26412341907e7e12041507489988265.jpeg",
      "__v":0,
      "subcategories":[  
          "Elektricne"
      ]
}
}

EDIT:

I also get this log when I trigger 'addToCart' request:

{ MongoError: The field 'items' must be an array but is of type object in 
document {_id: ObjectId('5a19ae2884d236048c8c91e2')}

Upvotes: 1

Views: 880

Answers (2)

Idan Dagan
Idan Dagan

Reputation: 11565

The comparison in $addToSet would succeeded only if the existing document has the exact same fields and values, and the fields are in the same order. Otherwise the operator will fail.

So in your case, request.item always need to be exactly the same.

I would recommend creating a model of "item". Then, your cart schema would be like:

var cartSchema = mongoose.Schema({
   mail: String,
   items: [{
        type: ObjectId,
        ref: 'item',
    }],
});

And let MongoDB determine if the item exist.

Upvotes: 1

El houcine bougarfaoui
El houcine bougarfaoui

Reputation: 37343

this should work you just need to implement objectExits function that test if the item is that one you're looking for :

Cart.findOne({ "mail": request.mail })
    .exec()
    .then(cart => {
        var replaced = cart.items.some((item, i) => {
            if (item._id == request.item._id)) {
                cart.items[i] = request.item;
                return true;
            }
        })
        if (!replaced) {
            cart.items.push(request.item);
        }
        cart.save();
        return cart;
    })
    .catch(err => {
        console.log(err)
    });

Upvotes: 0

Related Questions