foo*_*bar 75 mongoose mongodb node.js
我试图让MongoDB根据其索引检测重复值.我认为这在MongoDB中是可能的,但是通过Mongoose包装器似乎已经破坏了.对于这样的事情:
User = new Schema ({
email: {type: String, index: {unique: true, dropDups: true}}
})
Run Code Online (Sandbox Code Playgroud)
我可以使用相同的电子邮件保存2个用户.该死.
这里也表达了同样的问题:https://github.com/LearnBoost/mongoose/issues/56,但那个线程已经老了,无处可去.
现在,我手动调用数据库来查找用户.由于"电子邮件"已编入索引,因此该电话费用并不昂贵.但让它本地处理仍然是件好事.
有人有解决方案吗?
foo*_*bar 79
哎呀!你只需要重启mongo.
jpi*_*ora 38
哎呀!你只需要重启mongo.
并重新索引!
在测试中,我刚做了一个:
mongo <db-name>
> db.<collection-name>.reIndex()
Run Code Online (Sandbox Code Playgroud)
虽然如果你有重要的数据,你可能只需要:
mongo <db-name>
> db.dropDatabase()
Run Code Online (Sandbox Code Playgroud)
小智 20
我遇到了同样的问题:我已经将已添加用户的数据添加email
到我们的字段中的唯一约束UserSchema
,并且仍然可以使用重复电子邮件保存用户.我通过执行以下操作解决了这个问题
1)从用户集合中删除所有文档.
2)从mongo shell执行命令:
db.users.createIndex({email: 1}, {unique: true})
关于第1步,请注意来自Mongo的文档:
如果集合已经包含违反索引的唯一约束的数据,则MongoDB无法在指定的索引字段上创建唯一索引.
https://docs.mongodb.com/manual/core/index-unique/
sol*_*333 13
我做过这样的事情:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const FooSchema = new Schema({
name: { type: String, required: true, index: true, unique: true }
});
const Foo = mongoose.model('Foo', FooSchema);
Foo.createIndexes();
module.exports = Foo
Run Code Online (Sandbox Code Playgroud)
我添加了Foo.createIndexes()
行 bc 我在运行代码时收到以下弃用警告:
(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.
Run Code Online (Sandbox Code Playgroud)
我不确定是否Foo.createIndexes()
是异步的,但 AFAIK 的事情似乎工作正常
Pie*_*oui 11
如果您在Mongo中留下了一些重复项,也会发生此行为.当你的应用程序启动时,Mongoose会尝试在Mongo中创建它们.
为防止这种情况,您可以通过以下方式处理此错误:
yourModel.on('index', function(err) {
if (err?) {
console.error err
}
);
Run Code Online (Sandbox Code Playgroud)
好的,我能够通过在字段上添加索引并设置唯一属性来从mongoshell中解决此问题:
db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});
Run Code Online (Sandbox Code Playgroud)
Shell应该以这种方式回应:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
Run Code Online (Sandbox Code Playgroud)
现在从mongoshell快速测试:
var doc = {fieldName: 'abc'};
db.<collectionName>.insert(doc)
Run Code Online (Sandbox Code Playgroud)
应该给:WriteResult({"nInserted":1})
但是当重复时:
db.<collectionName>.insert(doc)
Run Code Online (Sandbox Code Playgroud)
会给:
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1 dup key: { : \"martyna@martycud.com\" }"
}
})
Run Code Online (Sandbox Code Playgroud)
根据文档:https : //docs.mongodb.com/v2.6/tutorial/modify-an-index/
要修改现有索引,您需要删除并重新创建索引。
不要重启 MONGO!
1 - 删除集合
db.users.drop()
Run Code Online (Sandbox Code Playgroud)
2 - 重新索引表
db.users.ensureIndex({email: 1, type: 1}, {unique: true})
Run Code Online (Sandbox Code Playgroud)
解决问题的步骤:
1 . 添加unique: true
到属性。
let schema = new mongoose.Schema(
{
name: {
type: String,
unique: true,
required: [true, "name required."],
}
}
);
module.exports = mongoose.model("role", schema);
Run Code Online (Sandbox Code Playgroud)
2 . 删除集合 - 例如role
(最后一行)
name
上图)有重复值3 . 重新启动使用mongoose
库的 Node.js 服务器。
这里的其他一些答案如何不正确?
该autoIndex
选项设置为true
重启数据库
in sequence
从应用程序级别强制执行唯一索引时,Mongoose有点松散; 因此,最好使用mongo cli从数据库本身强制执行您的唯一索引,或者unique
通过在UserSchema之后编写以下代码行来明确告诉mongoose您认真对待索引:
UserSchema.index({ username: 1, email: 1 }, { unique: true});
这将在UserSchema中的两个username
和email
字段上强制执行唯一索引.干杯.
在以下任一情况下,Mongoose 将默默地无法添加唯一索引:
在第一种情况下,用 列出索引,用db.collection.getIndexes()
删除旧索引db.collection.dropIndex("index_name")
。当您重新启动 Mongoose 应用程序时,它应该正确添加新索引。
在第二种情况下,您需要在重新启动 Mongoose 应用程序之前删除重复项。
小智 5
这是一个老问题,但对于仍然遇到此问题的人来说,您可能没有正确应用索引:
如果您将autoIndex
连接选项设置为,false
那么一个选项是使其成为一个true
或完全删除此属性,true
这会将其恢复为默认值,但是,在生产中不建议这样做,因为它会导致性能下降,更好的方法是显式调用createIndexes
您的模型,这将正确创建模式中定义的索引。
因此原始问题中示例的语法如下:
const userSchema = new mongoose.Schema({
email: { type: String, required: true, index: true, unique: true },
// other fields
});
// methods, statics, hooks... etc
const User = mongoose.model("User", userSchema);
User.createIndexes();
module.exports = User;
Run Code Online (Sandbox Code Playgroud)