E11000 MongoDB/Mongoose 重复键错误

Posted

技术标签:

【中文标题】E11000 MongoDB/Mongoose 重复键错误【英文标题】:E11000 duplicate key error with MongoDB/Mongoose 【发布时间】:2018-10-12 00:09:39 【问题描述】:

我有一个用户模型架构、一个工作模型架构和一个评论模型架构。这些架构之间的关系是用户可以提交许多作品(如博客文章),并且可以评论/评论(我们称之为评论)其他人的帖子(作品)。

因此,当用户提交评论(将其视为评论)时,这就是我的发帖路线。我通过 id 找到工作,然后创建一个新的批评模型对象,并将其传递给 .create() mongoose 函数。一切似乎都很顺利,直到我点击foundWork.critiques.push(createdCritique) 行。控制台日志错误说:

BulkWriteError: E11000 重复键错误集合:zapper.critiques index: username_1 dup key: : null

显然,对象中有两个用户名键并且它们相互冲突,但我对此还不够熟悉,无法找到问题的根源并在 mongoose 模型中修复它。型号如下。如果有人可以提供帮助,将不胜感激。

// post route for getting the review
router.post('/:id', isLoggedIn, function(req, res) 

    Work.findById(req.params.id, function(err, foundWork) 
        if (err) 
            console.log(err);
         else 

            // create a new critique
            var newCritique = new Critique (
                reviewerName: 
                    id: req.user._id,
                    username: req.user.username
                ,
                work: 
                    id: foundWork._id,
                    title: foundWork.title
                ,
                critique : req.body.critique,
                date: Date.now(),
                rating: 0
            );

            // save new critique to db
            Critique.create(newCritique, function(err, createdCritique) 
                if (err) 
                    console.log(err)
                 else 
                    console.log("Created critique is ");
                    console.log(createdCritique);

                    // push the new critique into array of critiques of the work
                    foundWork.critiques.push(createdCritique);
                    // save to db
                    foundWork.save();                                
                
            );
        
    );

用户模型:

var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');

var UserSchema = new mongoose.Schema(
    firstname: String,
    lastname: String,
    username: String,
    password: String,
    email: String,
    zip: String,
    bio: 
        type: String,
        default: ''
    ,
    influences: 
        type: String,
        default: ''
    ,
    favBooks: 
        type: String,
        default: ''
    ,
    notWriting: 
        type: String,
        default: ''
    ,
    favHero: 
        type: String,
        default: ''
    ,
    favVillain: 
        type: String,
        default: ''
    ,
    works: [
        
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Work'
        
    ],
    critiques: [
        
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Critique'
        
    ],
    friends: [
        
            friendId: String,
            friendName  : String,
            friendPic: String
        
    ],
    friendRequests: [
        
            sendingFriendId: String,
            sendingFriendName  : String,
            sendingFriendPic: String
        
    ],
    createdDate: 
        type: Date,
        default: Date.now
    ,
    lastLogin: 
        type: Date,
        default: Date.now
    
);

UserSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("User", UserSchema);

工作模式:

var mongoose = require('mongoose');

var WorkSchema = new mongoose.Schema(
    title: String,
    genre: String,
    workType: String,
    length: Number,
    ageRange: String,
    author: 
        id: 
            type: mongoose.Schema.Types.ObjectId,
            ref: "User"
        ,
        username: String
    ,
    manuscriptText: String,
    critiques: [ 
        
            id: 
                type: mongoose.Schema.Types.ObjectId,
                ref: "Critique"
            
        
    ],
    ratingNumber: [Number],
    ratingSum: 
        type: Number,
        default: 0
    ,
    date: 
        type: Date,
        default: Date.now
    ,
    isPublic: 
        type: Boolean,
        default: true
    
);


module.exports = mongoose.model("Work", WorkSchema);

批评模型:

var mongoose = require('mongoose');
var passportLocalMongoose = require('passport-local-mongoose');

var CritiqueSchema = new mongoose.Schema(
    reviewerName: 
        id: 
            type: mongoose.Schema.Types.ObjectId,
            ref: "User"
        ,
        username: String
    ,
    work: 
        id: 
            type: mongoose.Schema.Types.ObjectId,
            ref: "Work"
        ,
        title: String
    ,
    critique: String,
    date: 
        type: Date,
        default: Date.now
    ,
    rating: [Number]
);


CritiqueSchema.plugin(passportLocalMongoose);
module.exports = mongoose.model("Critique", CritiqueSchema);

【问题讨论】:

【参考方案1】:

当您在 MongoDB 中创建唯一索引时,默认行为是它也会索引空值。

这意味着如果您的集合中有一个用户名为 null 的文档,则不能添加另一个用户名为 null 的文档。

您需要的是 a sparse index,它只索引实际值(并忽略该字段为 null 的文档)。

Check this link 它展示了如何在 mongoose 中创建稀疏索引与“正常”索引(索引:true,vs 备用:true)。大多数时候,您需要稀疏索引。

【讨论】:

以上是关于E11000 MongoDB/Mongoose 重复键错误的主要内容,如果未能解决你的问题,请参考以下文章

E11000 mongodb mongoose 中的重复键错误索引

E11000 mongodb mongoose 中的重复键错误索引

MongoDB / Mongoose 一对多关系

如何使用用户名和密码连接 mongodb(mongoose)?

MongoDB、Mongoose 和复合 _id

mongodb -mongoose 增删查改