我有一个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
是由一个单独的进程运行的,因此在我的测试用例设置中重新启动它会很麻烦,而且我希望不必要。这是一个错误还是我错过了什么?
答案 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()});"