E11000 MongoDB猫鼬中的重复键错误索引


227

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

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

这就是我将其保存在数据库中的方式-

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

错误 -

{"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中有条目,也会引发错误“ Duplicate”错误


1
发生了同样的错误!在开发过程中,我们禁用了自动索引,并使用了小写的模式名称/键。我们后来决定改用TitleCase,但未能更新索引名称(即:titleCase代替TitleCase)。因此,当启用索引功能时,会出现此错误。花了一点时间弄清楚。您将要确保所有名称/键在任何地方都准确命名。
Jeach,

5
我有同样的错误,将猫鼬模型设置unique: false为没有任何影响。我意识到我必须先放下桌子,然后它才能工作。你可以像这样做db.whateverthecollection.drop({})。请注意,它会删除集合。
Pere

1
_id:添加
mongoose.Types.ObjectId,

Answers:


239

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

相关文档:

如果文档在唯一索引中没有索引字段的值,则索引将为此文档存储一个空值。由于存在独特的约束,MongoDB将只允许一个缺少索引字段的文档。如果存在多个没有索引字段值的文档,或者缺少索引字段,则索引构建将失败,并出现重复的键错误。

您可以将唯一性约束与稀疏索引结合使用,以从唯一性索引中筛选出这些空值并避免错误。

唯一索引

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

换句话说,稀疏索引可以处理多个文档 null值的。

稀疏索引


来自评论:

您的错误表明该键已命名mydb.users.$email_1,这使我怀疑您在users.email和上都具有索引users.local.email(该键现在已旧且未使用)。从猫鼬模型中删除字段不会影响数据库。检查mydb.users.getIndexes()是否存在这种情况,并使用手动删除不需要的索引mydb.users.dropIndex(<name>)


1
我刚刚删除了该空文档,它起作用了:) +1 ..thx寻求帮助
Trialcoder 2014年

70
您的错误表明该键已命名mydb.users.$email_1,这使我怀疑您在users.email和上都具有索引users.local.email(该键现在已旧且未使用)。从猫鼬模型中删除字段不会影响数据库。检查mydb.users.getIndexes()是否存在这种情况,并使用手动删除不需要的索引mydb.users.dropIndex(<name>)
RickN 2014年

17
或者,db.users.dropIndexes()如果要进行多个索引更改,请使用
cs_stackX 2014年

1
当我使用mongoose插件password-local-mongoose而不为新用户设置用户名时,这对我来说是个问题。
sshow 2016年

1
这是一个问题或观点,或者甚至是观点,@ titoih-是空值还是缺少值就像其他值一样是值还是特殊情况?“ a @ bc”和“ a @ bc”是相同的,“无”和“无”也一样吗?对于非稀疏索引,在MongoDB中答案为“是”。其他数据库(例如MySQL)会说“否”。
RickN

64

如果您仍在开发环境中,那么我将删除整个数据库,并从新的架构开始。

从命令行

 mongo
use dbName;
db.dropDatabase();
exit

46
我认为此解决方案非常激进,db.collection.dropIndexes()就像cs_stackX所说的那样,我认为就足够了
JorgeGarza '16

2
@JorgeGarza我有同样的问题。我刚放下收藏夹,此后一切开始正常运行。
Sandip Subedi '16

我不小心用两个字段的唯一ID初始化了集合。后来,当我想使用相同的ID添加多个文档时,直到删除集合并重新访问它,我才让我这么做。
Meir Snyder

1
如果您是开发的新手,这是一个很好的机会进行试验并弄清楚如何解决此问题……而不是在已经存储了千兆字节的用户数据时遇到此问题
Janac Meena

@JorgeGarza的评论很有道理。重新启动服务器后,删除的索引将由架构文件再次重建。此外,它也起作用。
retr0

26

检查收集索引。

由于字段集合中的索引已过时,因此出现了该问题,该索引应通过其他新路径存储。

当您将字段指定为唯一时,猫鼬会添加索引。


21

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

假设我们在架构的早期没有定义唯一索引,然后使用相同的电子邮件地址或没有电子邮件地址(空值)的2个用户进行了注册。

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

您基本上有三个选择:

  1. 删除收藏集

    db.users.drop();

  2. 查找具有该值的文档并将其删除。假设该值为空,您可以使用以下方法将其删除:

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

  3. 删除唯一索引:

    db.users.dropIndex(indexName)

我希望这可以帮助:)


18

我想向5岁的孩子解释这个问题的答案/解决方案,这样每个人都可以理解。

我有一个应用程序。我希望人们使用他们的电子邮件,密码和电话号码进行注册。在我的MongoDB数据库中,我想根据他们的电话号码和电子邮件来唯一地识别人员-因此这意味着每个人的电话号码和电子邮件都必须是唯一的。

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

那些没有电子邮件地址的人已经向我保证,他们将在下周之前拥有一个电子邮件地址。但是我还是要他们注册-所以我告诉他们在他们将电子邮件输入字段留空的情况下继续注册他们的电话号码。

他们这样做。

我的数据库需要一个唯一的电子邮件地址字段-但是我有很多人以“ null”作为他们的电子邮件地址。因此,我转到代码中,告诉我的数据库架构允许空/空电子邮件地址字段,稍后当承诺下周将电子邮件添加到个人资料中的人时,我将使用电子邮件唯一地址填充该字段。

因此,它现在对每个人都是双赢的(但是您;-]):人们注册,我很高兴拥有他们的数据……并且我的数据库很高兴,因为它被很好地使用了……但是您呢?我还没有提供构成架构的代码。

这是代码: 注意:电子邮件中的稀疏属性告诉我的数据库允许空值,之后将使用唯一值填充空值。

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编码/黑客!


如果你想有一个sparse索引和unique验证,以及具有被其他领域要求你需要使用partialFilterExpression选项。看到这个答案stackoverflow.com/a/34600171/728287
Gianfranco P.19年


4

在这种情况下,登录Mongo会找到您不再使用的索引(在OP中为“ email”)。然后选择掉落指数 在此处输入图片说明


3

这是我的相关经验:

在“用户”模式中,我将“名称”设置为唯一键,然后运行一些执行,我认为这已经建立了数据库结构。

然后,我将唯一键更改为“用户名”,并且在将数据保存到数据库时不再传递“名称”值。因此,mongodb可能会自动将新记录的“名称”值设置为null,这是重复键。{name: {unique: false, type: String}}为了覆盖原始设置,我尝试将“用户”模式中设置的“名称”键设置为非唯一键 。但是,它没有用。

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

只需设置一个随机键值,该键值在保存数据记录时就不会与“名称”键重复。简单地,Math方法'' + Math.random() + Math.random() 会生成随机字符串。


12
我认为这不是一个有效的解决方案,只是掩盖了问题。
里克(Rick)

丑陋但务实
安东尼

3

我遇到过同样的问题。尝试调试不同的方式无法解决。我尝试删除该集合,之后效果很好。如果您的收藏集中有很多文档,这不是一个好的解决方案。但是,如果您处于开发的早期阶段,请尝试删除该系列。

db.users.drop();


2

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


2

我也遇到了这个问题,我解决了。此错误表明此处已经存在电子邮件。因此,您只需要从“电子邮件模型”属性中删除此行。

unique: true

即使不起作用,也有可能。因此,只需要从MongoDB中删除集合,然后重新启动服务器即可。


1

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

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

从“更改”到“安全”的迁移更改已为我解决了。

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

1

从架构移除属性之后,同样的问题后,首先在保存时建立一些索引。从架构中删除属性会导致不存在的属性(仍具有索引)的值为空。从这里删除索引或从头开始创建新集合会有所帮助。

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


1

当我尝试修改使用mangoose定义的架构时,我遇到了相同的问题。我认为问题是由于创建集合时需要执行一些基础过程,例如描述对用户隐藏的索引(至少在我的情况下),所以我发现的最佳解决方案是删除整个集合然后重新开始。


0

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



-3

更改集合名称(如果它已经存在于数据库中),它将显示错误。如果给定任何属性作为唯一属性,则将发生相同的错误。


-4

遇到相同的问题,我通过删除unique属性来解决了该问题。

只是找到另一种方法来验证或检查模式的唯一属性值。


您应该在解决方案中提供一个示例。
Josh Adams

首先清除集合和/或从mongo数据库中删除整个集合是可行的,但这是一个临时解决方案。即使它们具有不同的ID,创建具有相似值的另一个记录仍然会给E11000重复键错误。我想允许该属性的重复值,所以我只是删除了唯一属性。
davyCode '18

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.