Fix: Mongoose Duplicate Key Error with Upsert

Updated: December 30, 2023 By: Guest Contributor Post a comment

Understanding the Error

The Mongoose duplicate key error occurs when you perform an upsert operation, which updates a document if it exists or creates a new one if it does not. This causes a conflict with unique indexes defined in your schema if the operation attempts to set the value of a field that is supposed to be unique to a value that already exists in another document.

Solutions

Handling Unique Constraints

To prevent this error, ensure that values for fields meant to be unique truly are unique. When you expect duplicates may occur, you may consider using another approach, such as adding a timestamp or a user ID to the value to ensure uniqueness.

Updating Indexes

Over time, schema definitions can evolve, and the existing index may enforce constraints based on outdated rules. Re-examine and drop outdated indexes if necessary, then recreate them according to the current schema. Use the MongoDB shell or Mongoose’s index management functions to handle such operations.

Error Handling in Code

When performing operations that could violate unique constraints, wrap them in a try-catch block to handle the error gracefully. Provide feedback to the user or system about the nature of the problem if encountered. Error handling allows you to mitigate the disruption of your application’s flow.

A Working Example

import mongoose from 'mongoose';

const userSchema = new mongoose.Schema({
  username: { type: String, unique: true },
  email: { type: String, unique: true }
});

userSchema.index({ username: 1, email: 1 }, { unique: true });

const User = mongoose.model('User', userSchema);

const upsertUser = async (userData) => {
  try {
    const options = { upsert: true, new: true, setDefaultsOnInsert: true };
    // Assume userData contains fields `username` and `email`.
    const result = await User.findOneAndUpdate({ email: userData.email }, userData, options);
    console.log('User upserted:', result);
  } catch (error) {
    if (error.code === 11000) {
      // Handle duplicate key error.
      console.error('Duplicate key detected:', error);
    } else {
      throw error; // Re-throw non-duplicate key related errors
    }
  }
};

// Connect to database and execute upsert
mongoose.connect('mongodb://localhost:27017/myDatabase');

upsertUser({ username: 'jdoe', email: '[email protected]' });

That’s it.