dropDatabase之后未强制执行唯一字段约束

时间:2015-01-07 05:21:56

标签: javascript node.js mongodb mongoose mongodb-query

我有一个Node / Mongoose / MongoDB项目,我使用Selenium WebDriver进行集成测试。我的测试用例设置的一部分是在每次测试之前擦除数据库。我通过命令行使用此处Delete everything in a MongoDB database

高度接受的方法完成此操作
mongo [database] --eval "db.dropDatabase();"

然而问题是,在运行此命令后,Mongo不再强制执行任何唯一字段,例如我的Mongoose Schema定义的以下字段:

  new Mongoose.Schema
    name :
      type : String
      required : true
      unique : true

如果我在mongod之后重新启动dropDatabase,则会再次强制执行唯一约束。

然而,由于我的mongod是由一个单独的进程运行的,因此在我的测试用例设置中重新启动它会很麻烦,而且我希望不必要。这是一个错误还是我错过了什么?

2 个答案:

答案 0 :(得分:1)

如您所述,您的mongod(或多个)是与您的应用程序分开的进程,因此您的应用程序不知道删除数据库时发生的情况。虽然默认情况下访问时会创建集合和数据库,但对于您定义的所有索引都不是这样。

索引创建实际上是在应用程序启动时发生的,正如文档中的段落所述:

  

当您的应用程序启动时,Mongoose会自动为架构中的每个已定义索引调用ensureIndex。 ...

每次访问模型时都不会自动发生,主要是因为这会产生过多的开销,即使索引到位且服务器什么都不做,它仍然是你不希望在每次“读​​取”之前的额外调用“,”更新“,”插入“或”删除“。

因此,为了让这种“自动”行为再次“激活”,您需要做的是“重新启动”您的应用程序,此过程将在连接时再次运行。同样,当您的“应用程序”无法连接到mongod进程时,它会重新尝试连接,并在重新连接时运行自动代码。

或者,您可以编写一个可以调用的函数来执行此操作并从API公开该方法,以便您可以将此函数与执行“drop database”之类的任何其他外部操作相关联:

function reIndexAllModels(callback) {
    console.log("Re-Indexing all models");
    async.eachLimit(
      mongoose.connection.modelNames(),
      10,
      function(name,callback) {
        console.log("Indexing %s", name);
        mongoose.model(name).ensureIndexes(callback);
      },
      function(err) {
        if(err) throw err;
        console.log("Re-Indexing done");
        callback();
      }
    );
}

这将遍历所有已注册的模型并重新创建分配给它们的所有索引。根据已注册模型的大小,您可能不希望在并行连接中运行所有这些。所以为了在这里帮助一点,我使用async.eachLimit以便将并发操作保持在可管理的数量。

答案 1 :(得分:0)

感谢Neil Lunn指出dropDatabase的陷阱并重新编制索引。最后,我使用了以下命令行解决方案,并删除了dropDatabase命令。

mongo [database] --eval "db.getCollectionNames().forEach(function(n){db[n].remove()});"