mongoose独特的索引不工作!
我试图让MongoDB检测基于其索引的重复值。 我认为这在MongoDB中是可能的,但是通过Mongoose包装,事情似乎被破坏了。 所以对于这样的事情:
User = new Schema ({ email: {type: String, index: {unique: true, dropDups: true}} })
我可以用相同的电子邮件保存2个用户。 该死。
同样的问题已经expression在这里: https : //github.com/LearnBoost/mongoose/issues/56 ,但那个线程是老的,并导致无处。
现在,我正在手动调用数据库来查找用户。 由于“电子邮件”被索引,该呼叫并不昂贵。 但是让它在本地处理还是很好的。
有没有人有这个解决scheme?
哎呀! 你只需要重新启动mongo。
哎呀! 你只需要重新启动mongo。
而且重新索引呢!
在testing中,我只是做了一个:
mongo <db-name> > db.dropDatabase()
虽然如果你有重要的数据,你可能只需要:
mongo <db-name> > db.<collection-name>.reIndex()
如果您在Mongo中留下了一些重复项,也会发生这种情况。 当您的应用程序启动时,Mongoose将尝试在Mongo中创build它们。
为了防止这种情况,你可以这样处理这个错误:
yourModel.on('index', function(err) { if (err?) { console.error err } );
我遇到了同样的问题:我已经添加了用户到数据库后,我们添加了唯一的email
字段限制到我们的UserSchema
,并仍然能够保存用户与愚蠢的电子邮件。 我通过下列方式解决了这个问题:
1)删除用户集合中的所有文档。
2)从mongo shell执行命令: db.users.createIndex({email: 1}, {unique: true})
关于第1步,请注意,从Mongo的文档:
如果集合已经包含违反索引唯一约束的数据,则MongoDB不能在指定的索引字段上创build唯一索引。
好吧,我可以通过在字段中添加索引并设置唯一属性来解决这个问题。
db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});
壳牌应该这样回应:
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
现在从mongoshell快速testing:
var doc = {fieldName: 'abc'}; db.<collectionName>.insert(doc)
应该给:WriteResult({“nInserted”:1})
但是当再次重复:
db.<collectionName>.insert(doc)
会给:
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\" }" } })
根据文档: https : //docs.mongodb.com/v2.6/tutorial/modify-an-index/
要修改现有的索引,您需要删除并重新创build索引。
不要重新启动MONGO!
1 – 删除collections
db.users.drop()
2 – 重新索引表格
db.users.ensureIndex({email: 1, type: 1}, {unique: true})
您也可以通过删除索引来解决此问题;
假设您想要从集合users
和字段username
删除唯一索引,请键入以下内容:
db.users.dropIndex('username_1');
如果表/集合为空,则为该字段创build唯一索引:
db.<collection_name>.createIndex({'field':1}, {unique: true})
如果表/集合不是空的,则删除集合并创build索引:
db.<collection_name>.drop() db.<collection_name>.createIndex({'field':1}, {unique: true})
现在重新启动mongoDB。
mongoose唯一的validation器
如何使用这个插件:
1)npm install –save mongoose-unique-validator
2)在你的模式中遵循本指南:
// declare this at the top var mongoose = require('mongoose'); var uniqueValidator = require('mongoose-unique-validator'); // exampleSchema = mongoose.Schema({}) etc... exampleSchema.plugin(uniqueValidator); // module.exports = mongoose.model(...) etc....
3)mongoose方法
当使用像findOneAndUpdate
这样的方法时,你需要传递这个configuration对象:
{ runValidators: true, context: 'query' }
ie. User.findOneAndUpdate( { email: 'old-email@example.com' }, { email: 'new-email@example.com' }, { runValidators: true, context: 'query' }, function(err) { // ... }
4)附加选项
-
不区分大小写
在架构中使用uniqueCaseInsensitive选项
ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }
-
自定义错误消息
ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });
现在,您可以添加/删除独特的属性到您的模式,而不用担心重新启动mongo,删除数据库或创build索引。
注意事项(来自文档):
由于我们依赖asynchronous操作来validation数据库中是否存在文档,因此可以同时执行两个查询,都返回0,然后都插入到MongoDB中。
在自动locking集合或强制单个连接之外,没有真正的解决scheme。
对于我们的大多数用户来说,这不会是一个问题,但是需要注意的是一个边缘案例。
最新回答:根本不需要重新启动mongodb,如果集群已经有了相同的名字索引,mongoose不会再重新创build索引,那么首先删除集群现有的索引,现在当你运行mongoose时,会创build新的索引上面的stream程解决了我的问题。