Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb Mongoose唯一索引不工作!_Mongodb_Node.js_Mongoose - Fatal编程技术网

Mongodb Mongoose唯一索引不工作!

Mongodb Mongoose唯一索引不工作!,mongodb,node.js,mongoose,Mongodb,Node.js,Mongoose,我试图让MongoDB根据索引检测重复值。我认为这在MongoDB中是可能的,但是通过Mongoose包装,东西似乎被破坏了。所以对于这样的事情: User = new Schema ({ email: {type: String, index: {unique: true, dropDups: true}} }) const mongoose = require('mongoose'); const Schema = mongoose.Schema; const FooSchema =

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

User = new Schema ({
  email: {type: String, index: {unique: true, dropDups: true}}
})
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
我可以用相同的电子邮件保存2个用户。该死

这里也表达了同样的问题:,但这条线索已经过时,没有任何结果

现在,我正在手动调用db以查找用户。这个电话并不昂贵,因为“电子邮件”是有索引的。但是,让它在本地处理还是很好的


有人能解决这个问题吗?

哎呀!你只需要重新启动mongo


哎呀!你只需要重新启动mongo

并重新编制索引,包括:

mongo <db-name>
> db.<collection-name>.reIndex()
mongo
>db..reIndex()
在测试中,由于我没有重要数据,您还可以:

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

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

要防止出现这种情况,可以通过以下方式处理此错误:

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

好的,通过在字段上添加索引并设置unique属性,我可以从mongoshell解决这个问题:

db.<collectionName>.ensureIndex({fieldName: 1}, {unique: true});
现在从mongoshell快速测试:

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

您还可以通过删除索引来解决此问题

假设要从集合
用户
和字段
用户名
中删除唯一索引,请键入以下内容:

db.users.dropIndex('username_1');

根据文档:

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

不要重启MONGO

1-删除集合

db.users.drop()
2-重新索引表格

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

我遇到了同样的问题:在已经将用户添加到数据库之后,我将
电子邮件
字段的唯一约束添加到了
用户模式
,并且仍然能够使用重复的电子邮件保存用户。我通过以下操作解决了此问题:

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

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

关于步骤1,请注意Mongo的文档:

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

如何使用此插件:

1) npm安装--保存mongoose唯一验证程序

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) 猫鼬方法

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

{runValidators:true,上下文:'query'}

ie. User.findOneAndUpdate(
      { email: 'old-email@example.com' },
      { email: 'new-email@example.com' },
      { runValidators: true, context: 'query' },
      function(err) {
        // ...
    }
4) 附加选项

  • 不区分大小写

    在模式中使用UniqueCaseSensitive选项

    ie.email:{type:String,index:true,unique:true,required:true,uniquecase不敏感:true}

  • 自定义错误消息

    ie.exampleSchema.plugin(uniqueValidator,{message:'Error,预期{PATH}是唯一的。})

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

    注意事项(来自文档):

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

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


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

    如果表/集合为空,则为字段创建唯一索引:

    db.<collection_name>.createIndex({'field':1}, {unique: true})
    
    db..createIndex({'field':1},{unique:true})
    

    如果表/集合不是空的,则删除集合并创建索引:

    db.<collection_name>.drop()
    db.<collection_name>.createIndex({'field':1}, {unique: true})
    
    db..drop()
    db..createIndex({'field':1},{unique:true})
    

    现在重新启动mongoDB。

    最新答案:根本不需要重新启动mongoDB, 如果colleciton已经有相同的名称索引,mongoose将不会重新创建 您的索引再次出现,因此,首先删除colleciton的现有索引, 现在,当您运行mongoose时,它将创建新索引,
    上述过程解决了我的问题。

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

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


    这将在用户架构中的
    用户名
    电子邮件
    字段上强制执行唯一索引。干杯。

    如果您在以下连接方法中使用选项
    自动索引:false

    User = new Schema ({
      email: {type: String, index: {unique: true, dropDups: true}}
    })
    
    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
    
    mongoose.connect(连接字符串,{autoIndex:false})


    试着把它去掉。如果这不起作用,请尝试重新启动mongodb,正如本线程中所建议的那样。

    我做了如下操作:

    User = new Schema ({
      email: {type: String, index: {unique: true, dropDups: true}}
    })
    
    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
    
    我添加了
    Foo.createIndexes()
    行b.c。在运行代码时,我收到了以下弃用警告:

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

    我不确定
    Foo.createIndexes()
    是否是异步的,但如果一切正常

    请检查模式中的自动索引是否为true,当您使用mongoose.connect选项时,它可能会设置为false(默认为true)

    您可以将模式定义为

    User = new Schema ({
      email: {
          type: String,
          unique: true
      }
    })
    
    但是,如果已经有一个文档,并且在此之后,您已经更改了用户的模式,那么这可能不起作用。如果不想删除此用户集合,可以在电子邮件上为此用户集合创建索引。使用此命令,您可以在电子邮件上创建索引

    db.User.createIndex({email:1},{unique: true})
    
    或者,您可以直接删除集合并添加
    User = new Schema ({
       email: {type: String, unique: true}
    });
    User.createIndexes();
    
    {
       "email": 1
    }
    
    db.users.remove({})
    
    const options = {
    // your options go here
    ...
    // this code is the solution
    audoIndex: true
    }
    mongoose.connect(DB_URI, options);
    
    let schema = new mongoose.Schema(
        {
            name: {
                type: String,
                unique: true,
                required: [true, "name required."],
            }
        }
    );
    
    module.exports = mongoose.model("role", schema);