Mongoose lets you define schema paths as
unique
, but theunique
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' });
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