下面是我的用户模式在user.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.email和req.body.password是抓取值。
我也检查了这篇文章,但没有帮助
如果我完全删除,然后它插入文档,否则它抛出错误“重复”错误,即使我在local.email中有一个条目
错误消息表示已经有一个记录,其中的电子邮件为null。换句话说,您已经有了一个没有电子邮件地址的用户。
相关文件:
If a document does not have a value for the indexed field in a unique index, the index will store a null value for this document. Because of the unique constraint, MongoDB will only permit one document that lacks the indexed field. If there is more than one document without a value for the indexed field or is missing the indexed field, the index build will fail with a duplicate key error.
You can combine the unique constraint with the sparse index to filter these null values from the unique index and avoid the error.
唯一索引
稀疏索引仅包含具有索引字段的文档条目,即使索引字段包含空值。
换句话说,稀疏索引适用于多个文档都具有空值的情况。
稀疏索引
评论:
您的错误显示键名为mydb.users。$email_1,这使我怀疑您有两个用户的索引。email和users.local.email(前者是旧的,目前未使用)。从Mongoose模型中删除字段不会影响数据库。检查mydb.users.getIndexes(),如果是这种情况,用mydb.users.dropIndex(<name>)手动删除不需要的索引。
我想像向一个5岁的孩子解释一样解释这个问题的答案/解决方案,这样每个人都能理解。
我有一个应用程序。我想让人们用他们的电子邮件、密码和电话号码来注册。
在我的MongoDB数据库中,我希望根据他们的电话号码和电子邮件唯一地识别人们——因此这意味着每个人的电话号码和电子邮件都必须是唯一的。
然而,有一个问题:我发现每个人都有电话号码,但不是每个人都有电子邮件地址。
那些没有电子邮件地址的人已经向我保证他们下周会有一个电子邮件地址。但我还是想让他们注册——所以我告诉他们继续注册他们的电话号码,因为他们的电子邮件输入字段是空的。
他们这样做。
我的数据库需要一个唯一的电子邮件地址字段-但我有很多人用“空”作为他们的电子邮件地址。所以我在我的代码中告诉我的数据库模式允许空/空的电子邮件地址字段,当那些承诺下周将电子邮件添加到他们的个人资料的人时,我将用电子邮件唯一地址填充这些字段。
所以现在对每个人来说都是双赢(除了你;-]):人们注册,我很高兴有他们的数据…我的数据库很高兴,因为它被很好地使用……但是你呢?我还没有给出创建模式的代码。
代码如下:
注意:在电子邮件中的稀疏属性,是什么告诉我的数据库允许空值,稍后将被填充为唯一的值。
var userSchema =新的猫鼬。模式({
本地:{
名称:{类型:字符串},
email:{类型:字符串,要求:true,索引:true,唯一:true,稀疏:true},
密码:{类型:字符串,要求:true},
},
facebook: {
id:{类型:字符串},
token:{类型:字符串},
email:{类型:字符串},
名称:{类型:字符串}
}
});
var User = mongoose.model('User',userSchema);
模块。出口=用户;
我希望我已经解释清楚了。
NodeJS编码/破解快乐!
编辑:这个解决方案在2023年仍然有效,你不需要丢弃你的收集或丢失任何数据。
以下是我在2020年9月解决同样问题的方法。有一个超级快速和简单的方法从mongodb图集(云和桌面)。可能以前没那么容易吧?这就是为什么我觉得我应该在2020年写下这个答案。
首先,我阅读了上面关于在mongoose模式上更改字段“unique”的一些建议。如果遇到这个错误,我假设您已经更改了模式,但尽管如此,您还是得到了一个500作为响应,并注意:指定重复的KEY!如果问题是由模式配置引起的,并且假设您已经配置了一个不错的中间件来记录mongo错误,那么响应将是400。
为什么会发生这种情况(至少是主要原因)
为什么呢?在我的例子中很简单,模式上的字段过去只接受唯一的值,但我只是将其更改为接受重复的值。Mongodb为具有唯一值的字段创建索引,以便更快地检索数据,因此在过去mongo为该字段创建了索引,因此即使在schema上设置“unique”属性为“false”后,Mongodb仍然使用该索引,并将其视为必须是唯一的。
如何解决
放弃这个指数。你可以在2秒内从Mongo Atlas或在Mongo shell上执行命令。为了简单起见,我将为不使用mongo shell的用户展示第一个。
去看看你的收藏。默认情况下,你在“查找”标签。只需选择右边的下一个:“Indexes”。您将看到同一个字段的索引仍然会给您带来麻烦。只需点击按钮“下降指数”。完成了。
因此,不要每次出现这种情况时都丢弃数据库
我相信这是一个更好的选择,而不仅仅是放弃整个数据库甚至是收藏。基本上是因为这就是为什么它在放弃整个集合后仍然有效。因为如果你的第一个条目使用你的新模式unique: false, mongo不会为这个字段设置索引。