L
L
low molecular macro2021-08-03 15:19:10
Mongoose
low molecular macro, 2021-08-03 15:19:10

How to fix the issue with adding an optional unique field?

When a user registers on the site, he does not need to indicate his email address. But if you did, then this email must be unique in the database. Here is a snippet of the schema:

const userSchema = new mongoose.Schema({
    username: {
        type: String,
        required: true,
    },
    name: {
        type: String,
        required: false,
    },
    email: {
        type: String,
        required: false,
        unique: true,
        lowercase: true,
    },

The problem appears when the user does not specify his mail, and an empty string comes from the form to the server. Then in my code it turns out that the first user who did not specify his mail receives an empty string in the email field. And since the email field in the database must be unique for each user, other users who have not specified email cannot be added.
I tried to fix it like this:
if (!email) {
    email = undefined;
}

but I still get this error:
MongoError: E11000 duplicate key error collection: test.users index: email_1 dup key: { email: null }

But shouldn't undefined values ​​be discarded when they are written to the database?
const newUser = await User.create({
      username,
      email,
      password
    });


I also wanted advice on this code snippet:
let query = User.find();
query = query.or([{ username }, { email }]);
query.projection("username email");
const result = await query;

if (result.some((e) => e.username === username)) {
    submitErrors.push("username_taken");
}

if (email && result.some((e) => e.email === email)) {
    submitErrors.push("email_taken");
}

Does it make sense to do something with query = query.or([{ username }, { email }]);for those cases when an empty string comes to the server instead of email? In order not to search in vain on an empty line?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Alexander Romanov, 2021-08-03
@molekulyarniy

The email field needs a sparse index
{unique: true, sparse: true}
For the second question, search with findOne
and $or only add if email exists
Something like this:

let query = {username};
if (email) {
  query = {$or:[{username},{email}]}
}
User.findOne(query)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question