在dropDatabase之后不执行唯一的字段约束

我有一个Node / Mongoose / MongoDB项目,我使用Selenium WebDriver进行集成testing。 我的testing用例设置的一部分是在每次testing之前擦拭数据库。 我通过使用在这里被大量接受的方法通过命令行来完成此操作删除MongoDB数据库中的所有内容

mongo [database] --eval "db.dropDatabase();" 

然而问题在于,运行这个命令之后,Mongo不再强制任何唯一的字段,比如我的Mongoose Schema定义的以下内容:

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

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

但是因为我的mongod是由一个单独的进程运行的,所以重启它作为我的testing用例的一部分会很麻烦,我希望不必要。 这是一个错误还是我错过了什么?

正如你所说的,你的mongod (或多个)是一个独立于你的应用程序的进程,因此你的应用程序不知道你丢弃数据库时发生了什么。 尽pipe默认情况下访问集合,实际上数据库也会被创build,但是您所定义的所有索引都不是这样。

索引创build实际上是在应用程序启动时发生的,正如文档中的这段话所指出的那样:

当您的应用程序启动时,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(); } ); } 

这将在所有注册模型中循环,并重新创build分配给它们的所有索引。 根据注册模型的大小,您可能不希望在并行连接中运行所有这些。 所以为了在这里提供一些帮助,我使用了async.eachLimit来保持并发操作的可pipe理性。

感谢Neil Lunn指出dropDatabase的缺陷并重新dropDatabase索引。 最后,我去了下面的命令行解决scheme,并删除dropDatabase命令。

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