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's
aggregate
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.