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

时间:2011-04-04 07:18:49

标签: mongodb node.js mongoose

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

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

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

这里也表达了同样的问题:https://github.com/LearnBoost/mongoose/issues/56,但是那个线程已经老了,无处可去。

现在,我手动调用db来查找用户。由于“电子邮件”已编入索引,因此该电话费用并不昂贵。但让它本地处理仍然是件好事。

有没有人有解决方案?

26 个答案:

答案 0 :(得分:76)

糟糕!你只需要重启mongo。

答案 1 :(得分:40)

  

糟糕!你只需要重启mongo。

并重新索引!

在测试中,我刚做了一个:

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

虽然如果你有重要的数据,你可能只需要:

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

答案 2 :(得分:17)

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

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

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

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

  

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

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

答案 3 :(得分:11)

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

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

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

答案 4 :(得分:9)

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

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

Shell应该以这种方式回应:

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

现在从mongoshell快速测试:

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

应该给:     WriteResult({&#34; nInserted&#34;: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\" }"
    }
})

答案 5 :(得分:5)

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

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

这将在UserSchema中的usernameemail字段上强制执行唯一索引。欢呼声。

答案 6 :(得分:4)


解决问题的步骤:

1。将 unique: true 添加到属性中。

let schema = new mongoose.Schema(
    {
        name: {
            type: String,
            unique: true,
            required: [true, "name required."],
        }
    }
);

module.exports = mongoose.model("role", schema);

2。删除集合 - 例如 role(最后一行)

  • 这是一种简单的修复方法 - 如果您已经有重复的值。
  • 您还可以删除集合中的所有记录,以便唯一列(上面的name)有重复值

3 .重新启动使用 mongoose 库的 Node.js 服务器。


这里的其他一些答案怎么不正确?

  • autoIndex 选项设置为 true

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

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

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

答案 7 :(得分:4)

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

  

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

不要重启MONGO!

1 - 删除集合

db.users.drop()

2 - 重新索引表格

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

答案 8 :(得分:4)

以下任何一种情况下,猫鼬都将无声地添加唯一索引:

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

在第一种情况下,使用db.collection.getIndexes()列出索引,并使用db.collection.dropIndex("index_name")删除旧索引。重新启动Mongoose应用程序时,应正确添加新索引。

在第二种情况下,您需要在重新启动Mongoose应用程序之前删除重复项。

答案 9 :(得分:4)

我已经做了类似的事情:

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()行。运行代码时,我收到以下弃用警告:

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

我不确定Foo.createIndexes()是否异步,但是AFAIK似乎运行正常

答案 10 :(得分:1)

检查架构中的autoIndex是否为true,使用mongoose.connect选项时可能将其设置为false(默认为true)

答案 11 :(得分:1)

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

答案 12 :(得分:1)

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

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

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

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

现在重启mongoDB。

答案 13 :(得分:1)

mongoose-unique-validator

如何使用此插件:

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

使用像findOneAndUpdate这样的方法时,您需要传递此配置对象:

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

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

    警告(来自文档):

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

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

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

答案 14 :(得分:1)

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

我们假设您要从集合users和字段username中删除唯一索引,请输入以下内容:

db.users.dropIndex('username_1');

答案 15 :(得分:0)

如果您在像这样的连接方法中使用选项autoIndex: false

mongoose.connect(CONNECTION_STRING, { autoIndex: false });

尝试将其删除。如果这不起作用,请尝试重新启动mongodb ,如该线程中建议的那样。

答案 16 :(得分:0)

您可以将架构定义为

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

但是,当已经有一个文档,之后又更改了用户的架构时,可能无法使用。如果您不想删除该用户集合,则可以在电子邮件上为其创建索引。使用此命令,您可以在电子邮件上创建索引。

db.User.createIndex({email:1},{unique: true})

或者您可以删除该集合并再次添加用户。
对于删除集合,您可以输入以下内容:

db.User.drop()

答案 17 :(得分:0)

一段时间以来,我遇到了同样的问题,做了很多搜索,而对我来说,解决方案是createIndexes()函数。

我希望有帮助。

所以代码将是这样。

User = new Schema ({
   email: {type: String, unique: true}
});
User.createIndexes();

答案 18 :(得分:0)

遇到此问题时,我尝试删除数据库,多次重新启动服务器(nodemon),但所有技巧都没有用。我通过Robo 3T找到了以下解决方法:

  1. 在Robo 3T中,双击“数据库”以打开收藏集
  2. 打开收藏夹以显示有问题的收藏夹。首先,请确保您的收藏集为空
  3. 右键单击“索引”文件夹。默认情况下,您将看到_id_作为默认值。现在,选择添加索引
  4. 例如,为电子邮件字段选择一个名称,例如说email
  5. 将密钥提供为JSON。例如

    {
       "email": 1
    }
    
  6. 单击“唯一”复选框

  7. 保存

这将确保在MongoDB中不会保存重复的电子邮件。

答案 19 :(得分:0)

请确保您的集合中没有多余的字段,只需在其上放置唯一索引即可。

然后重新启动您的应用程序(猫鼬)。 只是默默地添加索引失败。

答案 20 :(得分:0)

从集合中删除所有文档:

db.users.remove({})

如其他人所述,重新启动对我有用

答案 21 :(得分:0)

如果您的MongoDB是作为服务工作的(简单的找到方法是如果不需要通过终端启动mongod.exe文件就不需要连接数据库),那么在进行更改之后,您可能需要重新启动服务和/或完全删除数据库。

这很奇怪,因为对于某些用户而言,只需删除一个集合即可。其中一些只需要删除数据库。但是这些对我没有用。我删除了数据库,然后重新启动了MongoDB Server服务。

要重新启动服务,请在Windows搜索栏中搜索服务,然后找到MongoDB服务,双击以打开,然后停止并再次启动该服务。

如果其他方法对您不起作用,我相信这会成功。

答案 22 :(得分:0)

在我看来,猫鼬已经过时了。我通过在CMD上运行过时的npm进行了检查。 并更新了“猫鼬”。

请告知这是否对您也有用。

答案 23 :(得分:0)

当您将数据库与应用程序连接时,请添加以下选项:“ audoIndex:true” 例如在我的代码中,我这样做:

#Section to enable node application chart on port 3000 
    location /chart {
            proxy_pass http://localhost:3000/;
    }

我还删除了我遇到问题的集合,并重新创建了它以确保它可以工作。 我在以下位置找到了该解决方案:https://dev.to/emmysteven/solved-mongoose-unique-index-not-working-45d5 我还尝试了“重启MongoDB”之类的解决方案,但对我不起作用。

答案 24 :(得分:0)

就我而言,我们需要定义 schema.index 来创建索引。 请查看 Mongoose 文档索引 https://mongoosejs.com/docs/guide.html#indexes,

  • 请注意,更改架构后,请记住重新启动服务器以进行检查。

现在看看下面的代码进行测试:

const schemaUser = new mongoose.Schema(
  {
    username: {
      type: String,
      required: true,
      index: true,
      unique: true,
      dropDups: true,
    },
    hash: String,
    created: {
      type: Date,
      default: Date.now,
    },
  },
  {
    autoCreate: true, // auto create collection
    autoIndex: true, // auto create indexes
  }
)
// define indexes to be create
schemaUser.index({ username: 1 })

const User = mongoose.model('Users', schemaUser)
const newUser = new Users({ username: 'wintzer' })
newUser.save(function (err) {
  if (err) console.log(err)
})

答案 25 :(得分:0)

重新启动和使用插件对我来说不起作用,而且使用插件来做一些我们都确信 mongo 可以自己做的事情有点矫枉过正。

所以这里是修复。在您的连接函数中,将此添加到选项对象(第二个参数)

const options = {
  autoIndex: true, //this is the code I added that solved it all
}
mongoose.connect(process.env.MONGO_URI, options);