mdash1
mdash1

Reputation: 1115

Mongoose, set default to null and unique

I am trying to create a User Schema that has a key of 'facebookid', which is a unique value that is only given when a user signs up with facebook, but not when a user signs up through google or locally. When a user signs up locally, the facebookid is set to null as a default. However I am getting the error: 'insertDocument :: caused by :: 11000 E11000 duplicate key error index: db22.users.$facebookid_1 dup key: { : null }'

Here is the Schema:

let UserSchema = new Schema({
    facebookid: {
        type: String,
        required: false, // only required for facebook users
        unique: true,
        default: null
    },
    // more details + keys below ...
})

So how can I allow duplicate entries for the key facebookid if the value is null if I also want entries to be unique?

i.e I don't want to see two similar String entries:
not okay:

* User: {_id: 123, facebookid: '4325',username:'joe'}
* User: {_id: 432, facebookid: '4325', username: 'pat'}

okay:

* User: {_id: 123, facebookid: null,username:'joe'}
* User: {_id: 432, facebookid: null, username: 'pat'}

Upvotes: 12

Views: 15684

Answers (3)

barakbd
barakbd

Reputation: 1102

Thanks @Mikas!

Extra bonus - you can refer nested keys as follows: "key1.key2".
Unfortunately, $ne is not supported (yet?), so you cannot use simply: $ne: null

    key1: {
        key2: {
            type: String,
            index: {
                unique: true,
                partialFilterExpression: {
                    "key1.key2": {
                        // $ne: null,
                        $type: Schema.Types.String
                    }
                },

            },
            default: null
        }

Upvotes: 4

Mika Sundland
Mika Sundland

Reputation: 18939

You can use partialFilterExpressions:

facebookid: {
  type: String,
  required: false, // only required for facebook users
  index: {
    unique: true,
    partialFilterExpression: { facebookid: { $type: 'string' } },
  },
  default: null,
 }

This allows null to be used several times.

Remember to restart Mongoose and all that after changing the unique constraints. See this question if you haven't already.

Upvotes: 14

Shaishab Roy
Shaishab Roy

Reputation: 16805

For that situation you should not use unique: true in schema but you have to check facebookid is already exist or not so you can add validation for facebookid using schemaName.path and check uniqueness. like bellow.

let UserSchema = new Schema({
    facebookid: {
        type: String,
        required: false,
        default: null
    },
    // more details + keys below ...
})

UserSchema.path('facebookid').validate(function(value, next){
  if(!value) {
    return next();
  }
  // I assueme your model name is User
  mongoose.models['User'].findOne({facebookid: value }, function(err, found){
    if(err){
      return next(false);
    }

    if(found && found.facebookid){
      return next(false, "Already exist this facebook ID");
    }else{
      return next();
    }
  });

});

Upvotes: 2

Related Questions