猫鼬独特的索引不起作用!

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.

  • 你是什​​么意思"oops你只需要重启mongo"?!你是说在不降低数据库的情况下添加索引是不可能的? (7认同)
  • 事实并非如此.您无需重新启动mongo即可添加索引. (5认同)
  • 我有同样的问题,但我无法找到如何在OSX上重启mongo.当我杀死进程时,它会自动再次生成,并且唯一索引仍然不起作用......任何想法? (4认同)
  • 我尝试重新启动。也重新索引。不得不删除数据库来解决这个问题。猜测问题是在添加索引之前已经存在重复项,因此在生产数据库中,我需要删除重复项然后重新启动? (2认同)

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)

  • db.dropDatabase()擦除数据库! (10认同)

小智 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)


sig*_*.pl 9

好的,我能够通过在字段上添加索引并设置唯一属性来从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)


Dam*_*ito 7

根据文档: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)


Man*_*ddy 6


解决问题的步骤:

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

    • 不需要,默认为 true
  • 重启数据库

    • 不需要,你只需要重启 Node.js 服务器

  • 按照以上3个步骤 in sequence
    • 如果你错过了什么,做2次


moe*_*dol 5

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

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

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

  • 派对有点晚了,但是在执行独特索引时"有点松散"的ORM有什么用呢? (3认同)

Der*_*ill 5

在以下任一情况下,Mongoose 将默默地无法添加唯一索引:

  1. 该集合已具有同名索引
  2. 该集合已包含具有索引字段重复项的文档

在第一种情况下,用 列出索引,用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)