首页 文章

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

提问于
浏览
165

以下是我在 user.js 模型中的 user 架构 -

var userSchema = new mongoose.Schema({
    local: {
        name: { type: String },
        email : { type: String, require: true, unique: true },
        password: { type: String, require:true },
    },
    facebook: {
        id           : { type: String },
        token        : { type: String },
        email        : { type: String },
        name         : { type: String }
    }
});

var User = mongoose.model('User',userSchema);

module.exports = User;

这就是我在我的控制器中使用它的方式 -

var user = require('./../models/user.js');

这就是我在db中保存它的方法 -

user({'local.email' : req.body.email, 'local.password' : req.body.password}).save(function(err, result){
    if(err)
        res.send(err);
    else {
        console.log(result);
        req.session.user = result;
        res.send({"code":200,"message":"Record inserted successfully"});
    }
});

Error -

{"name":"MongoError","code":11000,"err":"insertDocument :: caused by :: 11000 E11000 duplicate key error index: mydb.users.$email_1  dup key: { : null }"}

我检查了db集合,没有这样的重复条目存在,让我知道我做错了什么?

仅供参考 - req.body.emailreq.body.password 正在获取值 .

我也检查过这篇文章但没有帮助STACK LINK

如果我完全删除然后它插入文档,否则它会抛出错误“重复”错误,即使我在local.email中有一个条目

17 回答

  • 15

    错误消息表示已经有 null 作为电子邮件的记录 . 换句话说,您已经拥有一个没有电子邮件地址的用户 .

    相关文件:

    如果文档没有唯一索引中索引字段的值,则索引将为此文档存储空值 . 由于唯一约束,MongoDB只允许一个缺少索引字段的文档 . 如果有多个文档没有索引字段的值或缺少索引字段,则索引构建将失败并出现重复键错误 . 您可以将唯一约束与稀疏索引结合使用,以从唯一索引中过滤这些空值并避免错误 .

    unique indexes

    稀疏索引仅包含具有索引字段的文档的条目,即使索引字段包含空值也是如此 .

    换句话说,稀疏索引可以使多个文档都具有 null 值 .

    sparse indexes


    来自评论:

    您的错误说该密钥名为 mydb.users.$email_1 ,这使我怀疑您在 users.emailusers.local.email 上都有索引(前者现在已经过时且未使用) . 从Mongoose模型中删除字段不会影响数据库 . 如果是这种情况,请检查 mydb.users.getIndexes() 并使用 mydb.users.dropIndex(<name>) 手动删除不需要的索引 .

  • 168

    如果您仍在开发环境中,我会删除整个数据库并重新开始使用新模式 .

    从命令行

    ➜ mongo
    use dbName;
    db.dropDatabase();
    exit
    
  • 47

    检查收集索引 .

    我有这个问题,因为字段集合中的过时索引应该由不同的新路径存储 .

    当您将字段指定为唯一时,Mongoose会添加索引 .

  • -5

    基本上这个错误就是说,你在特定字段上有一个唯一的索引,例如:“email_address”,所以mongodb期望集合中每个文档的唯一电子邮件地址值 .

    因此,我们可以说,在您的架构中,未定义唯一索引,然后您使用相同的电子邮件地址或没有电子邮件地址(空值)注册了2个用户 .

    后来,你看到有一个错误 . 因此,您尝试通过向架构添加唯一索引来更正它 . 但是您的集合已经有重复项,因此错误消息表明您无法再次插入重复值 .

    你基本上有三个选择:

    • 删除集合

    db.users.drop();

    • 找到具有该值的文档并将其删除 . 假设值为null,您可以使用以下命令将其删除:

    db.users.remove({ email_address: null });

    • 删除唯一索引:

    db.users.dropIndex(indexName)

    我希望这有帮助:)

  • 2

    我遇到了类似的问题,我只是清除特定字段的索引,然后它的工作对我来说 . https://docs.mongodb.com/v3.2/reference/method/db.collection.dropIndexes/

  • -1

    我想解释这个问题的答案/解决方案就像我向一个5岁的孩子解释一样,所以每个人都能理解 .

    我有一个app.I希望人们注册他们的电子邮件,密码和电话号码 . 在我的MongoDB数据库中,我想根据他们的电话号码和电子邮件识别出唯一的人 - 这意味着电话号码和电子邮件必须对每个人都是唯一的 .

    但是,有一个问题:我已经意识到每个人都有一个电话号码,但不是每个人都有一个电子邮件地址 .

    那些没有电子邮件地址的人已经答应我,他们将在下周收到一个电子邮件地址 . 但我还是希望他们注册 - 所以我告诉他们继续注册他们的电子邮件,因为他们将电子邮件输入字段留空了 .

    他们这样做了 .

    我的数据库需要一个唯一的电子邮件地址字段 - 但我有很多人使用'null'作为他们的电子邮件地址 . 因此,我转到我的代码并告诉我的数据库架构允许空/空电子邮件地址字段,当我们承诺将在下周将其电子邮件添加到其配置文件时,我将在后面填写电子邮件唯一地址 .

    所以它现在对每个人来说都是双赢的(但是你; - )):人们注册,我很高兴有他们的数据...我的数据库很高兴,因为它被很好地使用...但你怎么样?我还没有给你制作模式的代码 .

    这是代码: NOTE : The sparse property in email , is what tells my database to allow null values which will later be filled with unique values .

    var userSchema = new mongoose.Schema({
      local: {
        name: { type: String },
        email : { type: String, require: true, index:true, unique:true,sparse:true},
        password: { type: String, require:true },
      },
      facebook: {
        id           : { type: String },
        token        : { type: String },
        email        : { type: String },
        name         : { type: String }
      }
    });
    
    var User = mongoose.model('User',userSchema);
    
    module.exports = User;
    

    我希望我能很好地解释它 . 快乐的NodeJS编码/黑客!

  • 2

    这是我的相关经历:

    在'User'模式中,我将'name'设置为唯一键,然后运行一些执行,我认为已经设置了数据库结构 .

    然后我将唯一键更改为'username',并且在将数据保存到数据库时不再传递'name'值 . 因此,mongodb可以自动将新记录的'name'值设置为null,这是重复键 . 我尝试将'name'键设置为'User'架构中的唯一键 {name: {unique: false, type: String}} ,以覆盖原始设置 . 但是,它没有用 .

    最后,我制定了自己的解决方案:

    只需在保存数据记录时设置一个不太可能与'name'键重复的随机键值 . Simply Math方法 '' + Math.random() + Math.random() 创建一个随机字符串 .

  • 1

    这是因为已经有一个具有相同名称和配置的集合 . 只需通过mongo shell从mongodb中删除该集合,然后重试 .

    db.collectionName.remove()

    现在运行你的应用程序它应该工作

  • 5

    我遇到过同样的问题 . 尝试调试不同的方法无法弄清楚 . 我尝试删除该集合,之后它运行良好 . 虽然如果您的馆藏有很多文件,这不是一个好的解决方案 . 但是,如果你处于早期开发状态,请尝试删除该集合 .

    db.users.drop();
    
  • 2

    我遇到了类似的问题,我意识到默认情况下mongo每个集合只支持一个模式 . 将新架构存储在其他集合中,或使用当前集合中的不兼容架构删除现有文档 . 或者找到一种方法,每个集合有多个模式 .

  • 7

    当我在config / models.js中进行以下配置时,我遇到了同样的问题

    module.exports.models = {
      connection: 'mongodb',
      migrate: 'alter'
    }
    

    将迁移从'alter'更改为'safe'为我修复了它 .

    module.exports.models = {
      connection: 'mongodb',
      migrate: 'safe'
    }
    
  • 1

    首次在保存时构建一些索引后从模式中删除属性后出现同样的问题 . 从架构中删除属性会导致非现有属性的空值,该属性仍具有索引 . 从头开始删除索引或从新集合开始有助于此 .

    注意:在这种情况下,错误消息将引导您 . 它有一条不再存在的路径 . 在我的情况下,旧路径是... $ uuid_1(这是一个索引!),但新的路径是.... * priv.uuid_1

  • 11

    当我尝试修改使用mangoose定义的模式时,我遇到了同样的问题 . 我认为这个问题是由于创建集合时有一些基础过程的原因,比如描述对用户隐藏的索引(至少在我的情况下) . 所以我找到的最佳解决方案是删除整个集合然后重新开始 .

  • 1

    我有同样的问题 . 问题是我从模型中删除了一个字段 . 当我删除数据库它修复

  • 7

    更改集合名称(如果它已存在于数据库中),它将显示错误 . 如果您将任何属性赋予唯一性,则会发生相同的错误 .

  • -2

    有同样的问题我通过删除属性上的 unique 属性解决了它 .

    只需找到另一种方法来验证或检查架构的唯一属性值 .

  • 1

    请清除集合或从MongoDB数据库中删除整个集合,稍后再试 .

相关问题