Mongoose findOneAndUpdate() executes multiple times

268 views Asked by At

Bit of background, I have an express backend for my application that is using MongoDB as a database. Auth0 is there as an identity provider.

I have an addTeamUser async function that:

  1. Validates the request body with Joi
  2. Takes an email from the request body
  3. Creates a user in the Auth0 database
  4. When successful, construct a user object with the auth0 id and email
  5. Push that user into an array of users in my local database using mongoose's findOneAndUpdate

The code is as shown below:

const addTeamUser = async (req) => {
  // Get team_id from JWT token
  const team_id = req.auth.team_id;
  const data = req.body;
  // Joi validation for the email body
  const { error } = schema.user.validate(data, { abortEarly: false });

  if (error) {
    return { message: error.message, statusCode: 400 };
  }

  try {
    // Call auth0 management API and create new user with the email provided and custom team_id in app_metadata
    const createdUser = await managementAPI.createUser({
      email: data.email,
      connection: 'Username-Password-Authentication',
      password: "changeme",
      app_metadata: {
        team_id: team_id,
      },
    });

    // Add user to local database if Management API returned a success
    const user = {
      id: createdUser.user_id,
      email: createdUser.email
    };

    const doc = await Team.findOneAndUpdate(
      { team_id },
      { $push: { users: user } },
      { new: true });

    return {
      statusCode: 201,
      users: doc.users,
      message: "User added successfully"
    }

  } catch (err) {
    console.error('Error creating user:', err);
    return { message: 'An error occurred, try again later', statusCode: 500 };
  }
};

Now this works like a charm... except that when the user is inserted in the local database, it sometimes inserts it twice and I end up with two of the same users in my array.

I've done a bit of reading and apparently I can't use await and callbacks at the same time but whatever I do to try to fix it, it will execute it twice.

Here's my Team Schema for more context:

const teamSchema = new Schema({
  team_id: {
    type: String,
    required: true
  },
  name: {
    type: String,
    required: true,
    trim: true,
  },
  users: [
    {
      id: {
        type: String,
        unique: true,
        required: true,
        trim: true
      },
      email: {
        type: String,
        unique: true,
        required: true,
        trim: true
      }
    }
  ],
}, {
  _id: false // This disables the automatic _id field for subdocuments
});

Please let me know what's going on with this bug and how do I fix it?

1

There are 1 answers

3
PTsag On

The reason the findOneAndUpdate method inserts the user two times in because of the {new:true} flag. So removing it will fix your problem. For more info check this previous question:

Document is inserted twice into MongoDB when using Mongoose create method