Sling Academy
Home/Node.js/Mongoose: How to update values in an array of objects

Mongoose: How to update values in an array of objects

Last updated: December 31, 2023

Mongoose ORM simplifies MongoDB interactions. This tutorial explores updating objects within a document’s array, highlighting the power and flexibility Mongoose offers with practical code examples.

Before we start writing code, ensure you have Node.js and MongoDB installed. Familiarity with Mongoose and basic JavaScript concepts like async/await is also needed.

Setting Up Mongoose

First, we set up Mongoose. Install it via npm and connect to your MongoDB database.

const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_database');

Defining The Schema

Define a schema that includes an array of objects, using a sample `Book` model with an array of `authors`.

const bookSchema = new mongoose.Schema({
  title: String,
  authors: [{ name: String, age: Number }]
});
const Book = mongoose.model('Book', bookSchema);

Basic Array Update

For a simple update, let’s use `findOneAndUpdate` along with the `$set` operator to modify an author’s name.

async function updateAuthor(bookId, authorId, newName) {
  const result = await Book.findOneAndUpdate(
    { _id: bookId, 'authors._id': authorId },
    { '$set': { 'authors.$.name': newName } },
    { new: true }
  );
  return result;
}

Adding to the Array

To add a new author, use `$push`:

async function addAuthor(bookId, author) {
  const result = await Book.findByIdAndUpdate(
    bookId,
    { '$push': { authors: author } },
    { new: true }
  );
  return result;
}

Removing from the Array

Use `$pull` to remove an author given a specific condition:

async function removeAuthor(bookId, authorName) {
  const result = await Book.findByIdAndUpdate(
    bookId,
    { '$pull': { authors: { name: authorName } } },
    { new: true }
  );
  return result;
}

Advanced Update Patterns

For complex updates, like incrementing age of all authors, combine `$inc` with the `$[]` all positional operator.

async function incrementAuthorsAge(bookId) {
  const result = await Book.updateOne(
    { _id: bookId },
    { '$inc': { 'authors.$[].age': 1 } }
  );
  return result;
}

Updating Multiple Array Items

When updating multiple items based on a condition, use the filtered positional operator.

async function updateMultipleAuthors(bookId, ageThreshold, newName) {
  const result = await Book.updateOne(
    { _id: bookId },
    { '$set': { 'authors.$[elem].name': newName } },
    { arrayFilters: [{ 'elem.age': { '$gte': ageThreshold } }] }
  );
  return result;
}

Conclusion

This tutorial covered updating array elements in Mongoose, showcasing flexibility from simple to complex scenarios, solidifying your backend development skills with MongoDB.

Next Article: Mongoose: How to use singular name for collection

Previous Article: Mongoose: How to connect to multiple databases

Series: Mongoose.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates