【问题标题】:duplicate key error when creating a new mongoose sub-document创建新的猫鼬子文档时出现重复键错误
【发布时间】:2014-07-10 11:54:15
【问题描述】:

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

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

我尝试插入的子文档被定义为具有 groupId 字段的子架构,该字段的要求为 {unique: true}、{sparse: true}。我用来做 upsert 的猫鼬方法调用是:

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

【问题讨论】:

  • 你能用文档的架构和使用的索引来扩展你的问题吗?
  • 如果您试图确保单个用户在groups 中不能有重复的组,那么这将不起作用。见stackoverflow.com/q/13907257/1259510
  • 我无法理解的是,为什么这个 userUpdate 有 _id?为了预防起见,只需在传递给 $push 之前从该 obj 中删除 _id 属性

标签: javascript mongodb mongoose


【解决方案1】:

如果您尝试从组数组更新现有组,$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){})

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      对 groupId 字段的 {unique: true} 要求意味着集合中的任何两个文档都不能包含相同的 groupId,而不是您想要的,从而强制文档中 groupId 的唯一性。您可以改用 MongoDB $addToSet 运算符来做您想做的事情。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-08-05
        • 2015-06-03
        • 1970-01-01
        • 1970-01-01
        • 2016-10-06
        • 2021-05-19
        • 2013-03-28
        • 1970-01-01
        相关资源
        最近更新 更多