1

I want my users to have a phone or an email (at least one of them) that's why I used these options for phone and email in my schema:

const schema = new Schema({

    phone: { type: String, unique: true, required: false },
    email: { type: String, unique: true, required: false },
    passwordHash: { type: String, required: true },
    role: { type: String, required: true },
    verificationToken: String

});

And this is the code to save a new doc to the collection:

async function register(params, origin) {

    // create account object
    console.log('params', params); 
    const account = new db.Account(params);

    // first registered account is an admin
    const isFirstAccount = (await db.Account.countDocuments({})) === 0;
    account.role = isFirstAccount ? Role.Admin : Role.User;
    account.verificationToken = randomTokenString();

    // hash password
    account.passwordHash = hash(params.password);

    console.log('account reached 1');

    // save account

    try {
        await account.save();
    } catch(err) {
        console.log(err) // this gets the error
    }
    

    console.log('account reached 2');



    console.log('account reached 3');

    return { success: true, msg: 'Registration successful' }

}

I sent two different types of params to the register function one with phone property and one with email. when I use the kind of params with email property everything works fine and I save a new user to the collection this is the console here:

enter image description here

But when I use phone instead of the email I get this error and nothing is saved into the collection:

enter image description here

How can I fix this error? I'm new to MongoDB.

Edit 1

I used this and the same error happens (this is the whole schema):

const schema = new Schema({

    phone: { type: String, required: false },
    email: { type: String, required: false },
    passwordHash: { type: String, required: true },
    title: { type: String, required: false },
    firstName: { type: String, required: false },
    lastName: { type: String, required: false },
    acceptTerms: Boolean,
    role: { type: String, required: true },
    verificationToken: String,
    verified: Date,
    resetToken: {
        token: String,
        expires: Date
    },
    passwordReset: Date,
    created: { type: Date, default: Date.now },
    updated: Date,
    userLevel: { type: String, default: 'starter' },
    cards: {
        starter : [unitSchema], 
        intermediate : [unitSchema], 
        advanced : [unitSchema],   
    }

});

schema.index({'phone': 1, 'email': 1}, {unique: true});

Edit 2

This is not working too:

const schema = new Schema({

    phone: { type: String, unique: true, required: false, sparse: true },
    email: { type: String, unique: true, required: false, sparse: true },
    ...

Edit 3

Used this but it's not working (something has changed or this is not the solution at all!!)

const schema = new Schema({

    phone: {
        type: String, 
        trim: true, 
        index: {
            unique: true,
            partialFilterExpression: {phone: {$type: "string"}}
        }
    }, 

    email: {
        type: String, 
        trim: true, 
        index: {
            unique: true,
            partialFilterExpression: {email: {$type: "string"}}
        }
    },

    // phone: { type: String, unique: true, required: false, sparse: true },
    // email: { type: String, unique: true, required: false, sparse: true },
    ...
halfer
  • 19,824
  • 17
  • 99
  • 186
Sara Ree
  • 3,417
  • 12
  • 48
  • in the error it says that the `email:null` is causing the duplicate key error, so it means there is already a document with a null email. I think using these options `unique: true, required: false` doesn't make sense, because null values will cause the duplicate key error. – SuleymanSah Jul 23 '21 at 19:09
  • I think when I add the first phone it works fine but after that for each phone the error reproduces? How can fix this ? I do'nt think I added a null email when I add the first phone but it seems monoDB thinks so... – Sara Ree Jul 23 '21 at 19:14
  • I want my users to have a phone OR an email that's why I used those options – Sara Ree Jul 23 '21 at 19:15
  • If you don't supply the email field, mongoose will insert null automatically – SuleymanSah Jul 23 '21 at 19:15
  • So what can I do for "I want my users to have a phone OR an email ..." – Sara Ree Jul 23 '21 at 19:15
  • Please help ... – Sara Ree Jul 23 '21 at 19:18
  • You can check this answer, `https://stackoverflow.com/a/37708894/11717458`, after the change in the schema, you may need to drop the existing collection. Another one is `https://stackoverflow.com/questions/16061744/mongoose-how-to-define-a-combination-of-fields-to-be-unique`. – SuleymanSah Jul 23 '21 at 19:18
  • I don't understand:( should I add this after my schema?: `schema.index({'phone': 1, 'email': 1}, {unique: true});` – Sara Ree Jul 23 '21 at 19:24
  • Yes under the schema definiton – SuleymanSah Jul 23 '21 at 19:24
  • Sorry it doesn't work, the same behavior again happened – Sara Ree Jul 23 '21 at 19:27
  • Please have a look at the EDIT 1. – Sara Ree Jul 23 '21 at 19:29
  • Then you can try the answers in `https://stackoverflow.com/questions/7955040/mongodb-mongoose-unique-if-not-null` or `https://stackoverflow.com/questions/35755628/unique-index-in-mongodb-3-2-ignoring-null-values` – SuleymanSah Jul 23 '21 at 19:30
  • I think maybe this is not the issue I never added a email field in the prams schema... – Sara Ree Jul 23 '21 at 19:32
  • Sara Edit 2 should work, but there is something important to make it work as stated in the answer. `Note that a unique, sparse index still does not allow multiple docs with an email field with a value of null, only multiple docs without an email field.` – SuleymanSah Jul 23 '21 at 19:46
  • Take the following steps, 1-) drop the collection. 2-) Remove the line `schema.index({'phone': 1, 'email': 1}, {unique: true});`, 3-) use these options `phone: { type: String, trim: true, index: true, unique: true, sparse: true }, email: { type: String, trim: true, index: true, unique: true, sparse: true },`, 4-) check if the mongoose could create the indexes on the collection, 5-) Don't pass empty field values as stated in the JohnnyHK's answer. – SuleymanSah Jul 23 '21 at 19:50
  • I'll test this but tell me why I have not any issue with adding multiple emails? I have the issue only when I try to add more than one phone number!!! – Sara Ree Jul 23 '21 at 19:52
  • If you have already a null email, and try to insert a null email, you'll also get the key error. – SuleymanSah Jul 23 '21 at 19:54
  • OHhhhhhhhhhhhhhhh.. finally a working answer... thanks I admit without you I couldn't solve this... if you create an answer it will be accepted... – Sara Ree Jul 23 '21 at 19:58
  • Good you solved the problem. I used anouther answer, so I will not post answer. You can delete the question if you want, I will mark this question as duplicate. – SuleymanSah Jul 23 '21 at 20:00

0 Answers0