在node.js应用程序中,我想使用insertMany
插入很多文档(实际上,大约是1万个)。我遇到以下问题:insertMany
(用await
调用)正在运行时,直到insertMany
调用完成之后,node.js进程才从处理循环中进行任何处理。>
这是预期的行为吗?我将如何“正确地进行”操作,以便我的服务在此期间仍能处理请求?我本来希望await insertMany
自动启用此功能,因为它是异步的,但似乎并非如此。
代码段:
exports.writeOrg = async (req, res, next) => {
logger.debug('orgs.writeOrg()');
// ...
try {
// ...
logger.debug('Starting processing of data.');
const newOrgDocs = await processLdapUsers(tenantId, ldapUsers);
logger.debug('Processing of data finished.');
const orgModel = getOrgModel(tenantId);
// Now delete the entire collection
logger.debug(`Delete entire org collection in tenant ${tenantId}`);
await orgModel.deleteMany({});
// And add the new org information; this replaces what was there before
logger.debug(`Inserting org structure to tenant ${tenantId}`);
// This is the call which seems to block: --->
await orgModel.insertMany(newOrgDocs);
// <---
logger.debug(`Finished inserting org structure to tenant ${tenantId}`);
// ...
} catch (err) {
// ...
// error handling
}
}
writeOrg
函数是一个常规的快速请求处理程序;有效负载是一个通常具有1000-20000条记录的JSON数组;在测试案例中,我有6000条记录,JSON总大小约为6 MB。本地写大约需要1.5秒,写到MongoDB Atlas(最便宜的测试层)大约需要20秒,这就是发生此问题的时间。
解决方法:如果我将数据分成较小的块,例如一次50条记录,事件循环会不时处理一些其他请求的数据。但是,尽管insertMany
函数是一个async
函数调用,所以我并不希望这样做。
答案 0 :(得分:0)
有很多问题使速度变慢,而最重要的实际上是问题中未提到的问题:我正在使用 Mongoose 作为Mongo DB的“ ORM”包装。我不知道这会对运行时产生如此大的影响。
在使用Chrome node.js调试工具检查了实际运行时之后,这里发生的事情是 Mongoose包装并验证数组中的每个文档,这会花费大量时间。
>BSON转换也需要时间,但是文档包装是最耗时的事情。
这意味着:猫鼬不是超级适合快速插入(或阅读,FWIW);如果您需要速度,则直接使用本机Mongo DB驱动程序是可行的方法。如果您对纯速度的需求不是很大,并且想要Mongoose的便利,则Mongoose可以通过执行验证和添加默认值等来增加价值。