0

In my user document, I want to individually index email and username as unique fields, so that a duplicate is never entered.

The problem is all of the documentation I have found for multiple unique indexes is for "Compound Indexing", which appears to somehow tie the second index to the first. I don't want that.

All I want is for in my signup step 1 if a user submits an email that already exists for MongoDB to return an error that it already exists, and exact same for step 2, when they set their username.

So I want them indexed and unique separate from each other. I'm using this now and it is tieing the 2 together somehow which is not what I want:

const UserSchema = new mongoose.Schema({
  email: {
    type: String,
    required: true,
    trim: true
  },
  username: {
    type: String,
    required: false,
    trim: true
  }
})

UserSchema.index({
  email: 1,
  username: 1
}, {
  unique: true
});

2 Answers 2

1

Mongoose doesn't have a built-in validation for unique fields. I recommend the package (with this you can use the unique validator on the email and username fields): mongoose-unique-validator. Extend your code with:

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

email: {
  type: String,
  required: true,
  trim: true,
  unique: true,
  index: true
},
  username: {
  type: String,
  required: false,
  trim: true,
  unique: true,
  index: true
}

UserSchema.plugin(uniqueValidator, {message: 'is already taken.'});
Sign up to request clarification or add additional context in comments.

1 Comment

So I have actually basically already implemented this mysef. Before any username or email is ever saved I "find" that email or username and if nothing comes up I allow it to continue. This works well except for the edge case where 2 of the same emails are saved at the exact same time and because my checks are async they could both be saved. This problem still exists with your package's solution. All I need is a way to have mongo uniquely index these 2 fields independently of each other so that mongo will never save if it already exists thus fixing my edge case.
0

Add unique: true to each field's definition in the schema to create separate, unique indexes for those fields:

const UserSchema = new mongoose.Schema({
  email: {
    type: String,
    required: true,
    trim: true,
    unique: true
  },
    username: {
    type: String,
    required: false,
    trim: true,
    unique: true
  }
})

See the Indexes section on this page for the documentation.

3 Comments

For whatever reason, this doesn't work. Somehow the first field is being associated with the second. I tried this and when I have a user in the signup process who has set an email but not set their username yet. Any other user who tries to sign up and save their email will get the mongo error that their email is not unique. What you have done is compound indexing. I need individual indexing.
They're individual indexes, but if username can be missing, you also need to make that index "sparse". Add sparse: true to the field definition to allow multiple "nulls". Note that you'll manually need to drop that index first as mongoose won't replace the existing index.
See here for a similar question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.