Sling Academy
Home/Node.js/Fixing Mongoose E11000 Duplicate Key Error Collection

Fixing Mongoose E11000 Duplicate Key Error Collection

Last updated: December 30, 2023

The Problem

The E11000 duplicate key error is a common issue that arises when working with Mongoose in a Node.js application, particularly concerning the indexing of documents in a MongoDB collection. This error occurs when a write operation attempts to insert or update a document in the collection with a value that already exists in a field that has a unique index. MongoDB enforces the uniqueness of index values and therefore will not allow two documents to have the same value for that indexed field.

Possible Solutions

Solving the Conflict with Index Keys

One way to resolve this problem is by ensuring that all values for fields with unique indexes are in fact unique. If your application logic inadvertently generates duplicate values for such fields, consider using UUIDs or another strategy for value generation that guarantees uniqueness. Ensuring uniqueness at the source can often preempt E11000 errors.

Schema Design and Indexes

Another solution involves inspecting the schema design. Let’s ensure that the field meant to be unique is correctly defined. A typical approach to defining an indexed field in a Mongoose schema looks like this:

const mongoose = require('mongoose');
const { Schema } = mongoose;

const userSchema = new Schema({
  email: { type: String, unique: true },
  // ... other fields
});

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

If an index was manually added in the MongoDB database after some documents were already created, this could have introduced duplicates, so it’s wise to build the index in a way that avoids conflicts with existing data.

Handling at Runtime

Errors cannot always be preempted, and your code should gracefully handle them. With Mongoose, you can intercept and inspect errors that occur during operations:

const saveUser = async (userData) => {
  const user = new User(userData);
  try {
    await user.save();
    console.log('User saved successfully!');
  } catch (error) {
    if (error.name === 'MongoError' && error.code === 11000) {
      console.error('There was a duplicate key error');
    } else {
      console.error('An error occurred:', error);
    }
  }
};

In this code snippet, we’re using async/await and encapsulating the save() operation within a try-catch block. If an E11000 error occurs, we’re checking the error code and logging it accordingly.

Updating Existing Documents

In some cases, if a conflict occurs, you might opt to update the existing document. This hinges on the specific application’s logic and requirements, but here is a simplified approach using Mongoose’s findOneAndUpdate method:

const updateOrSaveUser = async (userData) => {
  try {
    const updatedUser = await User.findOneAndUpdate(
      { email: userData.email },
      userData,
      { new: true, upsert: true }
    );
    console.log('User updated or inserted:', updatedUser);
  } catch (error) {
    console.error('An error occurred:', error);
  }
};

This method will search for a user by email and either update that user’s information or insert it if no document is found, effectively upserting the document while handling unique constraint errors internally.

Migrating Pre-Existing Data

If you’ve inherited a code base that did not enforce uniqueness from the start, there may be a need to clean up pre-existing data. This could include writing a migration script to resolve any duplicates. Depending on the complexity of the dataset and the field with the duplicate key error, you may merge records, delete duplicates, or assign unique values.

These solutions should give you a comprehensive approach to avoid the Mongoose E11000 error by ensuring there is no duplication in unique fields, improving schema designs, handling exceptions properly, and migrating pre-existing data if necessary.

Next Article: Mongoose: How to connect to multiple databases

Previous Article: How to Perform Case-Insensitive Queries in Mongoose

Series: Mongoose.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates