How to Add, Remove and Update items in a MongoDB Array using Mongoose

How to Add, Remove and Update items in a MongoDB Array using Mongoose

While performing CRUD operations on a MongoDB document can be fairly straightforward by using queries provided by Mongoose, You might be creating a REST API where you need to perform operations on an array in MongoDB. MongoDB provides us with a certain set of operators to work with arrays, the concept behind these operators are similar to the array operations you perform using Vanilla JS. We'll be exploring how to use these operators using a simple e-commerce cart as an example.

Prerequisite-

  • Basic understanding of Mongoose Schema and writing queries (eg-findOneAndUpdate)

  • some understanding of express.js

Let's get started!

Creating a Schema

We'll need a schema for our cart which will have an array to store the products that we'll be adding

const mongoose = require("mongoose");
const { Schema } = mongoose;

const CartSchema = new Schema(({
  userid: { type: Schema.Types.ObjectId },
  createdAt: { type: Date, default: Date.now },
  products: [{ 
    productid:String,
    productName:String,
    quantity: Number }]
}))

const Cart = mongoose.model("Cart", CartSchema);
module.exports = { Cart }

The only thing we need to focus is on the products array defined in the schema.

Adding an Item using $push

{ $push:{ 'array-name' : 'data you want to add' }}

Let's assume our user is logged in and wants to add an item to the cart. We need the user id to find the Cart document associated with the user and the product details that need to be added to the products array.

  try {
    const { productsDetails } = req.body;
    const { userid } = req.params;
    const data = await Cart.findOneAndUpdate({ userid: userid }, 
    { $push: { products: productDetails } };
    res.json(data);
  } catch (error) {
    //error message
  }

In the above example, we're using the Cart model we created initially to find the cart collection stored in the database and we're using the $push operator to push the data into the array.

Updating an Item using $set

{ $set:{ 'array-name.$.field-to-be-updated' : 'updated value' }}

We'll be updating the quantity of the product that is set to 1 when you initially add it. For updating this quantity field we need the product id to find the product and update the field.

// This is what our product array might look like
//products:[{ productid:"1234",productName:"JBL headphones",quantity:1}]

  try {
    const { updatedQuantity } = req.body;
    const { product_id } = req.params;
    const data = await Cart.updateOne({ userid:user_id, products.productid: prod_id}, 
    { $set: { products.$.quantity: updatedQuantity } };
    res.json(data);
  } catch (error) {
    //error message
  }

MongoDB then searches the Cart document required for that particular user using userid :user_id and returns the product we're looking for using products.productid: prod_id. Once the product is returned the $set operator does its job by replacing the previous value with the new value.

Deleting an Item using $pull

{ $pull:{ array-name :{ condition to find the product } }}

The $pull operator will remove the value from the array that matches the specified condition.

  try {
    const { updatedQuantity } = req.body;
    const { product_id } = req.params;
    const data =  await Cart.findOneAndUpdate({ user: userid }, 
    { $pull: { products: { productid: product_id } } }
      );
    res.json(data);
  } catch (error) {
    //error message
  }

There might be multiple products in the array. The product that needs to be removed from the cart can be located on any index inside the array. The sole purpose of using $pull instead of $pop is that the former removes the element according to the condition matched whereas the latter can only be used to remove the last or the first element from the array, which is not a proper use case for our cart.

Bonus

Avoid duplication when adding in an array

For certain use cases, we might not want duplicate items in an array. Let's say we have a video playlist, it's quite unusual to have two same videos in the same playlist. MongoDB provides an operator $addToSet.

  try {
    const { productsDetails } = req.body;
    const { userid } = req.params;
    const data = await Cart.findOneAndUpdate({ userid: userid }, 
    { $addToSet: { products: productDetails } };
    res.json(data);
  } catch (error) {
    //error message
  }

$addToSet adds a value to an array if and only it doesn't already exist in the array. it ensures that there are no duplicate items added to the array.

The End!

Thanks for reading, I hope this article helps you get started on working with arrays in MongoDB. Cheers!