Mongoose lets you define schema paths as unique, but the unique option has a few important caveats. Here’s what you need to know.

The unique option tells Mongoose that each document must have a unique value for a given path. For example, below is how you can tell Mongoose that a user’s email must be unique.

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  email: {
    type: String,
    unique: true // `email` must be unique
  }
});
const User = mongoose.model('User', userSchema);

If you try to create two users with the same email, you’ll get a duplicate key error.

// Throws `MongoError: E11000 duplicate key error collection...`
await User.create([
  { email: 'test@google.com' },
  { email: 'test@google.com' }
]);

const doc = new User({ email: 'test@google.com' });
// Throws `MongoError: E11000 duplicate key error collection...`
await doc.save();

Updates can also throw a duplicate key error. For example, if you create a user with a unique email address and then update their email address to a non-unique value, you’ll get the same error.

await User.create({ email: 'test2@google.com' });

// Throws `MongoError: E11000 duplicate key error collection...`
await User.updateOne({ email: 'test2@google.com' }, { email: 'test@google.com' });

Index, Not Validator

A common gotcha is that the unique option tells Mongoose to define a unique index. That means Mongoose does not check uniqueness when you use validate().

await User.create({ email: 'sergey@google.com' });

const doc = new User({ email: 'sergey@google.com' });
await doc.validate(); // Does not throw an error

The fact that unique defines an index as opposed to a validator is also important when writing automated tests. If you drop the database the User model is connected to, you’ll also delete the unique index, and you will be able to save duplicates.

await mongoose.connection.dropDatabase();

// Succeeds because the `unique` index is gone!
await User.create([
  { email: 'sergey@google.com' },
  { email: 'sergey@google.com' }
]);

In production you normally wouldn’t drop the database, so this is rarely an issue in production.

#mongoose #mongodb #developer

Understanding `unique` in Mongoose
2.40 GEEK