Updating multiple MongoDB documents - NodeJS: A BulkWrite Journey

Hey there! We're diving into the world of MongoDB and tackling a common scenario: updating existing data to include a new field. Specifically, we'll be adding a "tenancyName" field to our "posts" collection, using the corresponding "tenancyName" from a "companies" collection.

This could be achieved using an update aggregation pipeline, but for educational purposes, we will get the Posts joined with Company data and then create an update array to use a bulkWrite.

Why use bulkWrite instead of iterating with update statements?

Let's break down the code and understand the process.

import { MongoClient } from 'mongodb'
import { IPost } from 'src/infrastructure/database/post/post.interface'

const uri = process.env.DB_MONGO_URI
const client = new MongoClient(uri)

async function updateCompaniesWithTenancyName() {
  try {
    await client.connect()

    const database = client.db(process.env.DB_NAME)
    const postsCollection = database.collection<IPost>('posts')
    const postsWithCompany = await postsCollection
      .aggregate([
        {
          $lookup: {
            from: 'companies',
            localField: 'companyId',
            foreignField: '_id',
            as: 'companyData',
          },
        },
      ])
      .toArray()

    const bulkedPosts = postsWithCompany.reduce((acc, currentPost) => {
      if (currentPost.companyData.length > 0) {
        const updateOnePost = {
          updateOne: {
            filter: {
              _id: currentPost._id,
            },
            update: {
              $set: {
                tenancyName: currentPost.companyData[0].tenancyName,
              },
            },
          },
        }
        acc.push(updateOnePost)
      }
      return acc
    }, [] as any)

    const result = await postsCollection.bulkWrite(bulkedPosts)
    console.log(
      `${result.matchedCount} document(s) matched the filter, updated ${result.modifiedCount} document(s)`,
    )
  } finally {
    await client.close()
  }
}

updateCompaniesWithTenancyName().catch(console.dir)

Execute the script using Node.js:

DB_MONGO_URI="[[YourMongoDB_URI]]" DB_NAME="[[YourMongoDBName]]" node '[[PathToYourJavaScriptFile]]'

\Don't forget to create your js file from this typescript example*

Step 1: Connecting to MongoDB

We start by establishing a connection to our MongoDB database using the MongoClient from the mongodb library. We use the uri variable, which holds the connection string, and create a new MongoClient instance.

Step 2: Accessing Collections

Once connected, we access the "posts" and "companies" collections using the db object. We'll be working with these collections to perform the update.

Step 3: Finding Posts with Company Data

The core of our update lies in the aggregate function. We use a $lookup stage to join the "posts" collection with the "companies" collection based on the "companyId" field. This creates a new field called "companyData" in each post document, containing the corresponding company information.

Step 4: Preparing Bulk Update Operations

We iterate through the results of the aggregation and build an array of update operations using the reduce function. For each post that has associated company data, we create an updateOne operation that sets the "tenancyName" field to the "tenancyName" from the company data.

Step 5: Executing the Bulk Update

Finally, we use the bulkWrite function on the "posts" collection to execute all the prepared update operations in a single batch. This ensures efficiency and minimizes the impact on the database.

Step 6: Logging the Results

After the update, we log the number of documents that matched the filter and the number of documents that were actually updated. This provides valuable feedback on the success of the operation.

Key Takeaways

  • MongoDB'saggregate function is powerful for data manipulation and joins.

  • Bulk operations are essential for efficient updates on large datasets.

  • Always remember to close the connection to the database after you're done.

This example demonstrates a common use case for updating data in MongoDB. By understanding the concepts of aggregation, joins, and bulk operations, you can confidently tackle similar tasks in your own projects.