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

下面是我在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 }"}

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

供你参考——req.body.emailreq.body.password是抓取值。

我也检查了这篇文章,但没有帮助堆栈的链接

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

493943 次浏览

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

相关文件:

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

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

唯一索引 .

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

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

稀疏索引


评论:

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

以下是我的相关体会:

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

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

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

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

检查收集索引。

我有这个问题,由于过时的索引收集字段,这应该由不同的新路径存储。

猫鼬添加索引,当你指定字段为唯一的。

如果您仍然在开发环境中,我会删除整个db,并使用新的模式重新开始。

从命令行

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

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

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

db.collectionName.remove ()

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

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

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

改变迁移从'alter'到'safe'固定它为我。

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

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

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

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

我也有同样的问题。尝试调试不同的方法都没有找到答案。我试过放弃这个系列,之后效果很好。尽管如果您的集合有很多文档,这不是一个好的解决方案。但是如果您处于开发的早期状态,请尝试删除集合。

db.users.drop();

当我试图修改使用mangoose定义的模式时,也遇到了同样的问题。我认为这个问题是由于在创建一个集合时做了一些底层的过程,比如描述对用户隐藏的索引(至少在我的情况下)。所以我找到的最好的解决方案是放弃整个系列,重新开始。

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

假设,在您的模式中,前面没有定义唯一索引,然后您使用相同的电子邮件地址或没有电子邮件地址(空值)注册了2个用户。

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

你基本上有三个选择:

  1. 删除集合

    db.users.drop(); < / p >

  2. 找到具有该值的文档并删除它。假设该值为空,你可以使用以下命令删除它:

    db.users.remove({ email_address: null }); < / p >

  3. 删除唯一索引:

    db.users.dropIndex(indexName) < / p >

我希望这对你有所帮助:)

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

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

然而,有一个问题:我发现每个人都有电话号码,但不是每个人都有电子邮件地址。

那些没有电子邮件地址的人已经向我保证他们下周会有一个电子邮件地址。但我还是想让他们注册——所以我告诉他们继续注册他们的电话号码,因为他们的电子邮件输入字段是空的。

他们这样做。

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

所以现在对每个人来说都是双赢(除了你;-]):人们注册,我很高兴有他们的数据…我的数据库很高兴,因为它被很好地使用……但是你呢?我还没有给出创建模式的代码。

下面是代码: 注意:在电子邮件中的稀疏属性,是什么告诉我的数据库允许空值,稍后将被填充为唯一的值。 < / >强

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编码/破解快乐!< / p >
我也遇到过这个问题,我解决了它。 此错误显示此处已经显示了电子邮件。所以你只需要从你的Model for email属性中删除这一行
unique: true

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

在这种情况下,登录到Mongo,找到你不再使用的索引(在OP的情况下是'email')。然后选择Drop Index enter image description here < / p >

这不是一个大问题,但像我这样的初级开发人员,我们知道这是什么样的错误,最后我们花了很长时间来解决它。

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

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

删除您的数据库,然后它将工作。

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

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

步骤2:直接启动mongo .exe或使用命令提示符将其最小化。

步骤3:直接或使用命令提示符启动mongo.exe,执行以下命令

i) 使用yourDatabaseName(如果你不记得数据库名称,可以使用显示数据库)

(二)db.dropDatabase ()

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

编辑:这个解决方案在2022年仍然有效,你不需要丢掉你的收藏或丢失任何数据。

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

首先,我读了上面的一些改变“独特”领域的建议。在mongoose模式上。如果你遇到这个错误,我假设你已经改变了你的模式,但尽管如此,你得到了一个500作为你的响应,并注意这一点:指定复制的钥匙!。如果问题是由模式配置引起的,并且假设您已经配置了一个不错的中间件来记录mongo错误,那么响应将是400。

为什么会发生这种情况(至少是主要原因)

为什么呢?在我的例子中很简单,模式上的字段过去只接受唯一的值,但我只是将其更改为接受重复的值。Mongodb 为具有唯一值的字段创建索引为了更快地检索数据,所以在过去mongo为那个字段创建了那个索引,所以即使设置了"unique"财产是“虚假的”;在模式上,mongodb仍然使用该索引,并将其视为惟一的。

如何解决

放弃这个指数。你可以在2秒内从Mongo Atlas或在Mongo shell上执行命令。为了简单起见,我将为不使用mongo shell的用户展示第一个。

去看看你的收藏。默认情况下,你是在“查找”;选项卡。只需选择右边的下一个:&;indexes &;。您将看到同一个字段的索引仍然会给您带来麻烦。只需点击“删除索引”按钮。完成。

因此,不要每次出现这种情况时都丢弃数据库

我相信这是一个更好的选择,而不仅仅是放弃整个数据库甚至是收藏。基本上是因为这就是为什么它在放弃整个集合后仍然有效。因为mongo不会为这个字段设置索引,如果你的第一个条目是使用“unique: false”的新模式。

Server response

云图

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

index:true,
unique:true,
sparse:true

我用这种方法解决了我的问题。

只要进入你的mongoDB账户->在最后一次收集时,删除数据库列。或者调用mongoDB compass,然后删除数据库,

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

在我的情况下,我只是忘记返回res.status(400)后找到该用户与req。电子邮件已经存在

转到数据库,单击该特定集合并删除除id之外的所有索引。before after < / p >