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

Posted

技术标签:

【中文标题】E11000 mongodb mongoose 中的重复键错误索引【英文标题】:E11000 duplicate key error index in mongodb mongoose 【发布时间】:2018-11-12 07:29:29 【问题描述】:

以下是我在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');

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

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 " 

我检查了数据库集合,不存在这样的重复条目,让我知道我做错了什么?

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

我也查看了这篇文章,但没有帮助STACK LINK

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

【问题讨论】:

有同样的错误!在开发过程中,我们禁用了自动索引并使用小写模式名称/键。我们后来决定改用 TitleCase,但未能更新我们的索引名称(即:titleCase 而不是 TitleCase)。所以当我们启用索引时,我们得到了这个错误。花了一点时间才弄清楚。您需要确保所有名称/键在任何地方都准确命名。 我遇到了同样的错误,将猫鼬模型设置为unique: false 没有任何影响。我意识到我必须先放下桌子,然后它才会起作用。你可以做类似db.whateverthecollection.drop() 的事情。小心,它会删除集合。 _id: mongoose.Types.ObjectId 添加,因为需要唯一的 id @Pere 我不相信这行得通,谢谢 【参考方案1】:

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

相关文档:

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

您可以将唯一约束与稀疏索引结合起来,从唯一索引中过滤掉这些空值并避免错误。

unique indexes

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

换句话说,稀疏索引适用于多个文档都具有null 值的情况。

sparse indexes


来自 cmets:

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

【讨论】:

我刚刚删除了那个空文档,它起作用了 :) +1 ..thx 的帮助 您的错误表明密钥被命名为mydb.users.$email_1,这让我怀疑您在users.emailusers.local.email 上都有索引(前者目前已旧且未使用)。从 Mongoose 模型中删除字段不会影响数据库。如果是这种情况,请检查mydb.users.getIndexes(),并使用mydb.users.dropIndex(<name>) 手动删除不需要的索引。 如果您要进行多个索引更改,请使用db.users.dropIndexes() 当我使用 mongoose 插件 passport-local-mongoose 而不为新用户设置用户名时,这对我来说是个问题。 这是一个问题或观点,甚至可能是意见,@titoih - 为 null 或缺少值 与任何其他值一样的值 还是特殊情况? “a@b.c”和“a@b.c”是一样的,“nothing”和“nothing”也一样吗?对于非稀疏索引,MongoDB 中的答案是“是”。其他数据库(如 mysql)会说“不”。【参考方案2】:

这是我的相关经验:

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

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

最后,我提出了自己的解决方案:

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

【讨论】:

我不认为这是一个有效的解决方案,你只是掩盖了问题。 丑陋但实用【参考方案3】:

检查集合索引。

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

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

【讨论】:

【参考方案4】:

如果您仍在开发环境中,我会删除整个数据库并重新开始使用您的新架构。

从命令行

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

【讨论】:

我认为这个解决方案非常激进,我认为 db.collection.dropIndexes() 正如 cs_stackX 所说的那样就足够了 @JorgeGarza 我遇到了同样的问题。我刚刚放弃了收藏,之后一切都开始正常了。 我不小心用我的两个字段的唯一 ID 初始化了集合。后来当我想添加多个具有相同 ID 的文档时,直到我删除集合并重新访问它才让我这样做。 如果您是开发新手,这是一个尝试并找出解决方法的好机会......而不是在您已经存储了千兆字节的用户数据后遇到这个问题跨度> @JorgeGarza 的评论很有道理。重新启动服务器时,架构文件将再次重建删除的索引。而且,它奏效了。【参考方案5】:

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

【讨论】:

【参考方案6】:

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

db.collectionName.remove()

现在运行你的应用程序,它应该可以工作了

【讨论】:

【参考方案7】:

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

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

将迁移从 'alter' 更改为 'safe' 为我解决了这个问题。

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

【讨论】:

【参考方案8】:

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

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

【讨论】:

【参考方案9】:

我也遇到过类似的问题, 我只是清除特定字段的索引然后它对我有用。 https://docs.mongodb.com/v3.2/reference/method/db.collection.dropIndexes/

【讨论】:

【参考方案10】:

我有同样的问题。尝试调试不同的方式无法弄清楚。我尝试删除该集合,之后效果很好。虽然如果您的收藏有很多文档,这不是一个好的解决方案。但是,如果您处于开发的早期状态,请尝试删除该集合。

db.users.drop();

【讨论】:

【参考方案11】:

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

【讨论】:

【参考方案12】:

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

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

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

你基本上有三个选择:

    放下收藏

    db.users.drop();

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

    db.users.remove( email_address: null );

    删除唯一索引:

    db.users.dropIndex(indexName)

我希望这会有所帮助:)

【讨论】:

【参考方案13】:

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

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

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

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

他们这样做。

我的数据库需要一个唯一的电子邮件地址字段 - 但我有很多人的电子邮件地址为“null”。所以我去我的代码并告诉我的数据库模式允许空/空的电子邮件地址字段,当那些承诺下周将他们的电子邮件添加到他们的个人资料的人时,我将用电子邮件唯一地址填写这些字段。

所以现在它对每个人来说都是双赢的(但你;-]):人们注册,我很高兴拥有他们的数据......我的数据库很高兴,因为它被很好地使用......但是什么关于你 ?我还没有给你创建架构的代码。

这里是代码: 注意:电子邮件中的 sparse 属性告诉我的数据库允许空值,这些空值稍后将被唯一值填充。

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 选项。看到这个答案***.com/a/34600171/728287【参考方案14】:

我也遇到过这个问题,我解决了。 此错误表明此处已存在电子邮件。因此,您只需从 Model for email 属性中删除这一行。

unique: true

这可能是有可能的,即使它不起作用。所以只需要从 MongoDB 中删除集合并重新启动服务器。

【讨论】:

【参考方案15】:

在这种情况下,登录 Mongo 找到您不再使用的索引(在 OP 的情况下为“电子邮件”)。然后选择删除索引

【讨论】:

感谢您提供此问题的图形解决方案!完美运行。 谢谢,它运行良好。这是我找到的唯一解决方案 谢谢你这对我有用。我只是在我的情况下删除了电子邮件和电话的索引。它对我有用【参考方案16】:

这不是什么大问题,但是像我这样的初学者级别的开发人员,我们会考虑这是什么类型的错误,最后我们浪费了大量的时间来解决它。

实际上,如果您删除数据库并再次创建数据库并尝试创建集合后,它将正常工作。

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

【讨论】:

【参考方案17】:

删除你的数据库,然后它会工作。

您可以执行以下步骤来删除您的数据库

第一步:进入mongodb安装目录,默认目录为“C:\Program Files\MongoDB\Server\4.2\bin

第二步:直接启动mongod.exe或使用命令提示符并最小化。

第三步:直接启动mongo.exe或使用命令提示符运行以下命令

i) 使用 yourDatabaseName(如果您不记得数据库名称,请使用 show databases

ii) db.dropDatabase()

这将删除您的数据库。 现在你可以插入数据了,它不会显示错误,它会自动添加数据库和集合。

【讨论】:

【参考方案18】:

这是我在 2020 年 9 月解决相同问题的方法。mongodb 地图集(云和桌面)中有一个超级快速和简单的方法。大概以前没那么容易吧?这就是为什么我觉得我应该在 2020 年写下这个答案。

首先,我阅读了以上关于更改猫鼬模式中“唯一”字段的一些建议。如果您遇到此错误,我假设您已经更改了架构,但尽管如此,您还是得到了 500 作为您的响应,并注意这一点:指定 duplicated KEY!。如果问题是由架构配置引起的,并且假设您已经配置了一个不错的中间件来记录 mongo 错误,那么响应将是 400。

这是为什么呢?在我的情况下很简单,它曾经只接受唯一值但我只是将其更改为接受重复值的模式上的那个字段。 Mongodb 过去为该字段创建了一个索引,因此即使在架构上将“unique”属性设置为“false”后,mongodb 仍在使用该索引。

解决方案?删除该索引。使用 Mongo Atlas 只需 2 秒即可完成。

转到您的收藏。默认情况下,您位于“查找”选项卡上。只需选择右侧的下一个:“索引”。您将看到仍然为同一字段提供索引如何给您带来麻烦。只需点击“删除索引”按钮。

我相信这是一个比放弃整个收藏更好的选择。基本上是因为这就是它在删除整个集合后起作用的原因。因为如果您的第一个条目使用带有“unique: false”的新模式,mongo 不会设置索引。

【讨论】:

【参考方案19】:

如果您处于开发的早期阶段:消除集合。否则:将这个添加到每个给你错误的属性(注意:我的英语不好,但我试着解释一下)

index:true,
unique:true,
sparse:true

【讨论】:

【参考方案20】:

我已经通过这种方式解决了我的问题。

只需进入您的mongoDB 帐户 -> Atlast 集合,然后删除您的数据库列。或者去mongoDB compass然后删除你的数据库,

当你在数据库中保存一些空值时,有时会发生这种情况。

【讨论】:

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

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

E11000 MongoDB/Mongoose 重复键错误

MongoDB E11000 重复键错误

Mongoose + Expressjs - E11000 重复键错误索引?

Mongoose - 由 :: 11000 E11000 重复键错误索引引起?

Mongoose - 由 :: 11000 E11000 重复键错误索引引起?