node.js Mongoose 唯一索引不起作用!

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5535610/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 13:59:25  来源:igfitidea点击:

Mongoose Unique index not working!

mongodbnode.jsmongoose

提问by foobar

I'm trying to let MongoDB detect a duplicate value based on its index. I think this is possible in MongoDB, but through the Mongoose wrapper things appear to be broken. So for something like this:

我试图让 MongoDB 根据其索引检测重复值。我认为这在 MongoDB 中是可能的,但是通过 Mongoose 包装器,事情似乎被打破了。所以对于这样的事情:

User = new Schema ({
  email: {type: String, index: {unique: true, dropDups: true}}
})

I can save 2 users with the same email. Darn.

我可以使用相同的电子邮件保存 2 个用户。该死的。

The same issue has been expressed here: https://github.com/LearnBoost/mongoose/issues/56, but that thread is old and lead to nowhere.

此处表达了相同的问题:https: //github.com/LearnBoost/mongoose/issues/56,但该线程很旧并且无处可去。

For now, I'm manually making a call to the db to find the user. That call is not expensive since "email" is indexed. But it would still be nice to let it be handled natively.

现在,我正在手动调用数据库以查找用户。由于“电子邮件”已编入索引,因此该调用并不昂贵。但是让它在本地处理仍然很好。

Does anyone have a solution to this?

有没有人有解决方案?

采纳答案by foobar

Oops! You just have to restart mongo.

哎呀!您只需要重新启动 mongo。

回答by jpillora

Oops! You just have to restart mongo.

哎呀!您只需要重新启动 mongo。

And re-index too, with:

并且也重新索引,使用:

mongo <db-name>
> db.<collection-name>.reIndex()

In testing, since I don't have important data, you can also do:

在测试中,由于我没有重要数据,你也可以这样做:

mongo <db-name>
> db.dropDatabase()

回答by Neil Strain

I ran into the same issue: I added the unique constraint for the emailfield to our UserSchemaafter already having added users to the db, and was still able to save users with dupe emails. I resolved this by doing the following:

我遇到了同样的问题:在已经将用户添加到数据库之后,我将email字段的唯一约束添加到我们UserSchema的,并且仍然能够使用欺骗电子邮件保存用户。我通过执行以下操作解决了这个问题:

1) Remove all documents from the users collection.

1) 从用户集合中删除所有文档。

2) From the mongo shell, execute the command: db.users.createIndex({email: 1}, {unique: true})

2)从mongo shell,执行命令: db.users.createIndex({email: 1}, {unique: true})

Regarding step 1, note that from Mongo's docs:

关于第 1 步,请注意来自 Mongo 的文档:

MongoDB cannot create a unique index on the specified index field(s) if the collection already contains data that would violate the unique constraint for the index.

如果集合已经包含违反索引的唯一约束的数据,MongoDB 无法在指定的索引字段上创建唯一索引。

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

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

回答by Pierre Maoui

This behavior happen also if you have left some duplicates in Mongo. Mongoose will try to create them in Mongo when your application starts up.

如果您在 Mongo 中留下了一些重复项,也会发生这种情况。当您的应用程序启动时,Mongoose 将尝试在 Mongo 中创建它们。

To prevent this, you can handle this error this way :

为了防止这种情况,您可以通过以下方式处理此错误:

yourModel.on('index', function(err) {
  if (err?) {
    console.error err
  }
);

回答by sigman.pl

Ok, i was able to resolve this from the mongoshell by adding the index on the field and setting the unique property:

好的,我能够通过在字段上添加索引并设置唯一属性来从 mongoshell 解决此问题:

db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});

Shell should respond in this way:

壳牌应该这样回应:

{
    "createdCollectionAutomatically" : false,
    "numIndexesBefore" : 1,
    "numIndexesAfter" : 2,
    "ok" : 1
}

Now to test quickly from the mongoshell:

现在从 mongoshell 快速测试:

var doc = {fieldName: 'abc'};
db.<collectionName>.insert(doc)

Should give: WriteResult({ "nInserted" : 1 })

应该给: WriteResult({ "nInserted" : 1 })

But when repeating again:

但是当再次重复时:

db.<collectionName>.insert(doc)

Will give:

会给:

WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: fuelConsumption.users.$email_1  dup key: { : \"[email protected]\" }"
    }
})

回答by solstice333

I've done something like this:

我做过这样的事情:

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

I added the Foo.createIndexes()line b.c. I was getting the following deprecation warning when the code was being ran:

我添加了Foo.createIndexes()行 bc 我在运行代码时收到以下弃用警告:

(node:21553) DeprecationWarning: collection.ensureIndex is deprecated. Use createIndexes instead.

I'm not sure if Foo.createIndexes()is asynchronous, but AFAIK things seem to be working fine

我不确定是否Foo.createIndexes()是异步的,但 AFAIK 的事情似乎工作正常

回答by moeabdol

Mongoose is a little loose when enforcing unique indices from the application level; therefore, it's preferred to either enforce your unique indices from the database itself using the mongo cli or explicitly tell mongoose that you're serious about the uniqueindex by writing the following line of code just after your UserSchema:

Mongoose 在从应用程序级别强制执行唯一索引时有点松散;因此,最好使用 mongo cli 从数据库本身强制执行您的唯一索引,或者unique通过在您的 UserSchema 之后编写以下代码行来明确告诉 mongoose 您对索引是认真的:

UserSchema.index({ username: 1, email: 1 }, { unique: true});

UserSchema.index({ username: 1, email: 1 }, { unique: true});

This will enforce the unique index on both usernameand emailfields in your UserSchema. Cheers.

这将在 UserSchema 中的usernameemail字段上强制执行唯一索引。干杯。

回答by Damien Romito

According the documentation : https://docs.mongodb.com/v2.6/tutorial/modify-an-index/

根据文档:https: //docs.mongodb.com/v2.6/tutorial/modify-an-index/

To modify an existing index, you need to drop and recreate the index.

要修改现有索引,您需要删除并重新创建索引。

DO NOT RESTART MONGO !

不要重启 MONGO!

1 - drop the collection

1 - 删除集合

db.users.drop()

2 - reindex the table

2 - 重新索引表

db.users.ensureIndex({email: 1, type: 1}, {unique: true})

回答by Isaac Pak

mongoose-unique-validator

猫鼬唯一验证器

How to use this plugin:

如何使用这个插件:

1) npm install --save mongoose-unique-validator

1) npm install --save mongoose-unique-validator

2) in your schema follow this guide:

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 methods

3)猫鼬方法

When using methods like findOneAndUpdateyou will need to pass this configuration object:

使用类似方法时,findOneAndUpdate您需要传递此配置对象:

{ runValidators: true, context: 'query' }

{ runValidators: true, context: 'query' }

ie. User.findOneAndUpdate(
      { email: '[email protected]' },
      { email: '[email protected]' },
      { runValidators: true, context: 'query' },
      function(err) {
        // ...
    }

4) additional options

4) 附加选项

  1. case insensitive

    use the uniqueCaseInsensitive option in your schema

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

  2. custom error messages

    ie. exampleSchema.plugin(uniqueValidator, { message: 'Error, expected {PATH} to be unique.' });

  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.' });

Now you can add/delete the unique property to your schemas without worrying about restarting mongo, dropping databases, or creating indexes.

现在,您可以向模式添加/删除唯一属性,而无需担心重新启动 mongo、删除数据库或创建索引。

Caveats (from the docs):

注意事项(来自文档):

Because we rely on async operations to verify whether a document exists in the database, it's possible for two queries to execute at the same time, both get 0 back, and then both insert into MongoDB.

因为我们依赖异步操作来验证数据库中是否存在一个文档,所以有可能两个查询同时执行,都返回0,然后都插入到MongoDB中。

Outside of automatically locking the collection or forcing a single connection, there's no real solution.

除了自动锁定集合或强制单个连接之外,没有真正的解决方案。

For most of our users this won't be a problem, but is an edge case to be aware of.

对于我们的大多数用户来说,这不是问题,而是需要注意的边缘情况。

回答by chen Hymany

Newest answer: there is no need to restart mongodb at all, if colleciton has same name indexes already, mongoose will not recreate your indexes again, so, drop colleciton's existing indexes firstly, and now, when you run mongoose, it will create new index, above process solved my problem.

最新答案:根本不需要重启mongodb,如果Colleciton已经有同名索引,mongoose不会再重新创建你的索引,所以,首先删除colleciton现有的索引,现在,当你运行mongoose时,它会创建新的索引,以上过程解决了我的问题。