Sling Academy
Home/Node.js/Fix: Mongoose Duplicate Key Error with Upsert

Fix: Mongoose Duplicate Key Error with Upsert

Last updated: December 30, 2023

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.

Next Article: Fix UnhandledPromiseRejectionWarning: MongooseServerSelectionError

Previous Article: MongooseJS: Cursor-Based Pagination Examples

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