Add a new field to all documents of a collection with the value from the document field into MongoDB (Mongoose) with records of 300K+ Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Add a new field to all documents of a collection with the value from the document field into MongoDB (Mongoose) with records of 300K+ without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I’m having difficulty with adding another field to all records of the user‘s collection with a value from each document. I’m familiar with using $set with db.model.updateMany, and $addFields with aggregation pipeline, I’ve used both to solve problems in the past, in this case, I have to perform some logics/calculation before adding the value, right here is where my problem lies.

Say, I have the schema like this:

{
  "users": [
    {
      "wallets": {...},
      "avatar": "",
      "isVerified": false,
      "suspended": false,
      "country": "Nigeria",
      "_id": "123",
      "resetPasswordToken": "",
      "email": "example@gmail.com",
      "phone": "08012398743",
      "name": "Agbakwuru Nnaemeka Kennedy ",
      "role": "user",
    },
    {...}
}

I want to add a new field phoneNumber, that will take the value of the existing field phone, but before adding, I’d like to run a logic on it, as some of the phone values are having whitespaces most of them are not correctly formatted, and I’d like to prepend the country code to the phone value, before adding it to the new phoneNumber field.

I was able to get this done using a cursor from Mongoose db.mode.aggregate method, with $match filter, and adding the field to each document with the aggregate $addFields pipeline, this prove to take a whole lot of time, I had to stop the operation as it’s taking too much time to run.

I’d like to believe there’s a better way out there, please, I will appreciate any help.

Edit:

Here’s the aggregation I’m using:

const userCursor = User.aggregate([{$match: {phone: {$exists: true}}}]);
for await (const doc of userCursor) {
  await User.findByIdAndUpdate(doc._id, {$set: {
          phoneNumber: convertPhoneNumber({phoneNumber: doc.phone.replace(/s+/g, "")})}
  });
}

The convertPhoneNumber is a helper method I defined in my utils to prepend the country dealing code to the phone number.

Answer

With the help of @Jeremy Thille‘s answer here I was able to solve it with MongoDB Compass mongo command line with the below snippet.

db.users.find({phone: {$exists: true}}).forEach( user => {
  const phone = user.phone.replace(/s+/g, "");
  const phoneNumber = `+234${phone.slice((phone.length - 10))}`;
  db.users.updateOne({_id: user._id}, {$set: {phoneNumber}});
})

Downside was it took like 10-15 minutes to update 300K documents, this was an outstanding improvement as against my initial implementation that took over a day just to update a few tens of thousands documents.

We are here to answer your question about Add a new field to all documents of a collection with the value from the document field into MongoDB (Mongoose) with records of 300K+ - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji