创建新的mongoose子文档时出现重复键错误

时间:2014-05-21 17:21:17

标签: javascript mongodb mongoose

创建新文档然后尝试插入新的子文档时,我收到此错误:

Object {error: "E11000 duplicate key error index: sales.users.$gro…p key:
        { : ObjectId('537b7788da19c4601d061d04') }"}
error: "E11000 duplicate key error index: sales.users.$groups.groupId_1
        dup key: { : ObjectId('537b7788da19c4601d061d04') }"
__proto__: Object

我试图插入的子文档被定义为具有需求{unique:true},{sparse:true}的groupId字段的子模式。用于进行upsert的mongoose方法调用是:

User.findByIdAndUpdate(userId,
                       { $push: { 'groups': userUpdate} },
                       function (err, obj) where userUpdate = { groupId: groupId }.  

删除索引后问题得到解决,不再出现此错误。

var UserSchema = new Schema({
    email: {
        type: String,
        required: true,
        unique: true
    },
    active: {
        type: Boolean,
        default: true
    },
    username: {
        type: String,
        required: true,
        unique: true
    },
    password: {
        salt: {
            type: String,
            required: true
        },
        hash: {
            type: String,
            required: true
        }
    },
    securityQuestion: {
        question: String,
        salt: String,
        hash: String
    },
    mobile: {
        PIN: Number,
        Number: Number
    },
    createDate: {
        type: Date,
        default: Date.now
    },
    updateDate: Date,
    lastLoginDate: Date,
    prevLoginDate: Date,
    passChangeDate: Date,
    locked: Boolean,
    lockDate: Date,
    failedCount: Number,
    failedDate: Date,
    profile: profile,
    preference: preference,
    courses: [UserCourseSchema],
    groups: [UserGroupSchema],
    rewards: [UserRewardSchema],
    roles: UserRoleSchema,
    scores: [UserScoreSchema]
});

var UserGroupSchema = new Schema({
    groupId: {
        type: Schema.Types.ObjectId,
        unique: true,
        sparse: true
    },
    joinDate: {
        type: Date,
        default: Date.now
    },
    receiveNotifications: {
        type: Boolean,
        default: true
    },
    isAdmin: {
        type: Boolean,
        default: false
    },
    isOwner: {
        type: Boolean,
        default: false
    },
    isModerator: {
        type: Boolean,
        default: false
    },
    updateDate: Date
});

3 个答案:

答案 0 :(得分:1)

如果要在对象数组上应用upsert,那么这将始终创建新文档,因为它不比较数组的子文档,并且在groupId上有唯一索引,因此它不允许您创建具有相同值的新记录。对于它,您应该找到该记录,如果存在,则更新它,否则创建新记录。

另一种最好的方法是使用 $ addToSet 。 希望这会有所帮助。

答案 1 :(得分:0)

groupId字段上的{unique:true}要求意味着集合中没有两个文档可能包含相同的groupId,而不是您想要的,强制文档中groupIds的唯一性。您可以使用MongoDB $addToSet运算符来执行您想要的操作。

答案 2 :(得分:0)

如果您尝试从groups数组更新现有组,则$ push不是解决方案。

User.findAndUpdate({_id:userId,'groups.groupId': userUpdate.groupId},
                       { $set: {'groups.$': userUpdate}},
                       function (err, obj){})

否则,如果存在,则其他建议的$ addToSet会将元素添加到集合中。

User.findByIdAndUpdate(userId,
                       { $addToSet : { 'groups': userUpdate} },
                       function (err, obj){})