Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

duplicate key error when creating a new mongoose sub-document

When creating new document and then try to upsert a new sub-document I get this error:

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

The sub-document I'm trying to insert is defined as sub-schema that has a groupId field with the requirements {unique: true}, {sparse: true}. The mongoose method call I'm using to do the upsert is:

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

After dropping the indexes the problem is fixed and this error no longer occurs.

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
});
like image 824
Nik Avatar asked May 21 '14 17:05

Nik


1 Answers

If you are applying upsert on array of object then this will always create new document as it do not compare sub documents of an array and you have unique index on groupId so it is not allowing you to create new record with the same value. For it you should find that record and if exists, then update it else create new record.

Another best way is to use $addToSet. Hope this helps.

like image 153
Sachin Avatar answered Oct 08 '22 02:10

Sachin