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唯一索引。

https://docs.mongodb.com/manual/core/index-unique/

好吧,我可以通过在字段中添加索引并设置唯一属性来解决这个问题。

 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)附加选项

  1. 不区分大小写

    在架构中使用uniqueCaseInsensitive选项

    ie. email: { type: String, index: true, unique: true, required: true, uniqueCaseInsensitive: true }

  2. 自定义错误消息

    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程解决了我的问题。