3

Im trying to create multiple accounts.

The first account always works, but when im trying to make a new one i get the following error:

BulkWriteError: insertDocument :: caused by :: 11000 E11000 duplicate key error index: db.users.$friends.userid_1  dup key: { : null }

The first user is fine, containing friends with an empty array, as i would like it to be.

But the next user is not created.

What do i have to do to fix this error?

The user schema piece of friends in users is the following:

   friends : [
    {
        userid : {type: String, default: '', unique: true },
    }
],
friendRequests: [
    {
        userid : {type: String, default: '', unique: true },
    }

EDIT:

i have been looking into https://docs.mongodb.com/manual/core/index-unique/#unique-index-and-missing-field but still couldnt make it work.

EDIT2:

By default, its not creating any friends or friendrequests.

EDIT3:

full code:

passport.use('local-signup', new LocalStrategy({
            usernameField : 'username',
            passwordField : 'password',
            passReqToCallback : true,
        },
        function(req, username, password, done) {
            process.nextTick(function() {
                console.log("doing local signup");
                username = username.toLowerCase();
                Account.findOne({username :  username }, function(err, user) {
                    var expr = "/admin/";
                    if (err) {
                        return done(err);
                    } else if (user) {
                        return done(null, false, 'That username is already taken.');
                    } else if(username.length < 3 || username.length >= 12) {
                        return done(null, false, 'Username has to be between 3 and 12 characters! :( '  + username);
                    } else if(/^[a-zA-Z0-9- ]*$/.test(username) == false) {
                        return done(null, false, 'You cant have any special characters!');
                    } else if(password.length < 5 || password.length > 15) {
                        return done(null, false, 'Password need to be 5-15 characters long!');
                    } else {

                        var newUser            = new Account();
                        newUser.username    = username;
                        newUser.password = newUser.encryptPassword(password);
                        newUser.save(function(err) {
                            if (err)
                                throw err;
                            return done(null, newUser);
                        });
                    }
                });

            });

        }));

user model:

var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var bcrypt   = require('bcrypt-nodejs');



var UserSchema   = new Schema({
    username: {type: String, index: { unique: true }},
    password: {type: String},
    salt: { type: String},
    hash: {type: String},
    gender : {type: String, default: 'male'},
    friends : [
        {
            userid : {type: String, default: '', unique: true },
        }
    ],
    friendRequests: [
        {
            userid : {type: String, default: '', unique: true },
        }
    ]

});
UserSchema.methods.encryptPassword = function(password) {
    return bcrypt.hashSync(password, bcrypt.genSaltSync(10));
}

UserSchema.methods.validPassword = function(password) {
    return bcrypt.compareSync(password, this.password);
}



module.exports = mongoose.model('Users', UserSchema);
9
  • Are you sure you need a unique index for friends.userid ? It means a person can be a friend of no more than 1 other person. You are modelling quite a lonely world then. Commented Feb 15, 2018 at 12:40
  • oh , you are right @AlexBlex , my idea was that the userid has to be unique tho. Commented Feb 15, 2018 at 12:40
  • That's fair restriction. People are quite unique individuals. The unique constraint should be on the user schema on id property then. If you are using default _id it is already unique. Commented Feb 15, 2018 at 12:43
  • delete previously created indexes? Commented Feb 15, 2018 at 12:47
  • @AlexBlex its updated now. see previous comment Commented Feb 15, 2018 at 12:47

1 Answer 1

1
+50

As noted in the comment Mongodb doesn't enforce uniqueness in array values inside single document.

So you have to handle the uniqueness in array inside the client code. You can use combination of strategy to handle the requirement for you.

First remove the unique index and use Mongoose unique array plugin to have mongoose check the uniqueness in the array when you create/update a document.

The plugin works for both scalar and document arrays.For your case you can do the following changes.

var uniqueArrayPlugin = require('mongoose-unique-array');
UserSchema.plugin(uniqueArrayPlugin);

This will enforce the validation through validator and should show you an validation message when you perform update/save operation.

As noted in the blog the unique plugin doesn't work when you use $push in update query.

You can use

Account.findOne({"friends.userid":{"$ne":inputuserid}}, {"$push":{"friends":new user doc}});

Read blog and usage examples from author for more information.

Sign up to request clarification or add additional context in comments.

Comments

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.