MongoDB重复键错误:集合中的重复键:null。

3

我试图创建多个账户。

第一个账户总是可以创建,但当我试图创建新账户时,会出现以下错误:

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

第一个用户没问题,包含一个空数组的朋友,正如我所希望的。

但是下一个用户没有被创建。

我该怎么做来修复这个错误?

在用户中的 friends 的模式片段如下:

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

编辑:

我一直在研究https://docs.mongodb.com/manual/core/index-unique/#unique-index-and-missing-field,但仍然无法使其工作。

编辑2:

默认情况下,它不会创建任何好友或好友请求。

编辑3:

完整代码:

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);
                        });
                    }
                });

            });

        }));

用户模型:

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);

这是公平的限制。人们都是非常独特的个体。唯一的约束应该在用户模式的id属性上。如果您使用默认的_id,它已经是唯一的了。 - Alex Blex
删除先前创建的索引? - Alex Blex
@Veeram,问题在于,虽然我正在创建这个用户(代码已更新),但我没有在朋友列表中添加任何内容。我希望它在用户获得朋友之前保持为空。因此不要默认创建一个数组。 - maria
你是否打算让好友列表在整个集合中保持唯一性?例如:在第一个文档中,用户A与用户B是好友,在第二个文档中,由于他已经与用户A是好友,所以用户C不能成为用户B的好友。这是你想要的吗?唯一性约束不会强制 friends 数组在单个文档内保持唯一性,也就是说,用户A可以在 friends 数组中多次添加用户B作为好友。 - s7vr
不行。我只对用户A在其列表中不能重复添加用户B感兴趣。 - maria
显示剩余4条评论
1个回答

1

正如在评论中所指出的,Mongodb不会在单个文档内强制执行数组值的唯一性。

因此,您需要在客户端代码中处理数组内的唯一性。您可以使用策略组合来满足您的需求。

首先删除唯一索引,并使用Mongoose唯一数组插件,让mongoose在创建/更新文档时检查数组中的唯一性。

该插件适用于标量和文档数组。对于您的情况,您可以进行以下更改。

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

这将通过验证器强制执行验证,并在执行更新/保存操作时显示验证消息。
如博客中所述,当您在更新查询中使用$push时,唯一插件无法正常工作。
您可以使用
Account.findOne({"friends.userid":{"$ne":inputuserid}}, {"$push":{"friends":new user doc}});

请阅读作者的博客使用示例以获取更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接