KiLLkInGLiOn ei
KiLLkInGLiOn ei

Reputation: 53

mongoose-unique-validator detects all inputs as already existed

I am trying to create a unique email value in MongoDB. I used mongoose-unique-validator to implement that but resulted in error claiming that my unique emails that I just inputted are already existed.

This is the error message I received from trying to input unique email.

"message": "User validation failed: email: Error, expected email to be unique., _id: Error, expected _id to be unique."

They said the Email and _id are not unique. But.., _id is an auto-generated value to be unique in MongoDB meaning that it should not be detected as a duplicated value.

I am not sure if that was caused by my own implementation so I would look forward to see any assumption or ways to debug to the root cause of this too. I tried restarting from fresh Mongo DB and manually inputting uniquely via Postman but still no hope.

These are a part of the codes that might be related to the data creation on MongoDB

UserModel.js

var uniqueValidator = require('mongoose-unique-validator');

const { Schema } = mongoose;

const UsersSchema = new Schema({
  email: { type: String, unique: true, required: true},
  hashedPassword: String,
  salt: String,
});

UsersSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });
UsersSchema.set('autoIndex', false);

Server.js ---- /api/users/register

const finalUser = new Users(user);
finalUser.setPassword(user.password);

finalUser.save((err, data) => {
  if (err) {
    return res.status(400).json(err)
  }
  return res.json({ user: finalUser.toAuthJSON() })
})

Additional Information

I tried this solution from Sritam to detect another email with the same value but it still claims that the inputted email is already existed.

UsersSchema.path('email').validate(async (value) => {
  const emailCount = await mongoose.models.User.countDocuments({email: value });
  return !emailCount;
}, 'Email already exists');

"message": "User validation failed: email: Email already exists"

Upvotes: 3

Views: 751

Answers (2)

Erik Daut
Erik Daut

Reputation: 11

You can use validateModifiedOnly option in Document.save(). _id and email fields will never be validated unless they are modified. The code should look like this:

finalUser.save({ validateModifiedOnly: true }, (err, data) => {
  if (err) {
    return res.status(400).json(err)
  }
  return res.json({ user: finalUser.toAuthJSON() })
})

Upvotes: 1

KiLLkInGLiOn ei
KiLLkInGLiOn ei

Reputation: 53

Found the issue and solution!

They are acting weird like in the question because the model was not initialized. I must perform Schema.init() before performing any model validation.

The solution is to add UsersSchema.init().then(() => {...your operation})

Now Server.js ---- /api/users/register should look like this.

Users.init().then(() => {   // where Users is my UsersModel
  finalUser.save((err, data) => {
    if (err) {
      return res.status(400).json(err)
    }
    return res.json({ user: finalUser.toAuthJSON() })
  })
})

Hope this helps other developers who experience similarly odd error!

Upvotes: 0

Related Questions