MongoDB Node.js 3.0.6中$out聚合需调用toArray()才生效问题
解决MongoDB Node.js驱动v3.0.6中$out聚合未生成目标集合的问题
我来帮你拆解这个问题的核心原因和解决办法:
问题根源
在你使用的MongoDB Node.js驱动v3.0.6版本中,aggregate()方法调用后不会立即执行聚合操作,它只会返回一个游标对象。只有当你调用游标上的执行方法(比如.toArray()、.forEach())或者手动遍历游标时,驱动才会真正向MongoDB服务器发送完整的聚合请求,触发整个管道的执行——包括$out写入新集合的步骤。
你当前的代码仅仅是初始化了游标,没有触发实际的执行流程,所以服务器根本没收到聚合指令,自然不会生成ProjectsByCreated集合,这也是为什么耗时只有1毫秒的原因:只是创建了游标对象,没有和服务器做实际交互。
解决方案
你只需要触发游标执行即可,这里提供几种常用方式:
方式1:调用.toArray()(最直观)
const aggregationSteps = [ { $group: { _id: '$created_at' } }, { '$out': 'ProjectsByCreated' } ]; // 调用.toArray()触发聚合执行,即使$out不返回结果,这一步也会让服务器完成管道操作 await collection.aggregate(aggregationSteps, { 'allowDiskUse': true }).toArray();
方式2:调用.forEach()(适合不需要返回结果的场景)
如果不需要获取聚合返回的文档(毕竟$out已经把结果写入新集合了),可以用空回调的.forEach()来轻量触发执行:
await collection.aggregate(aggregationSteps, { 'allowDiskUse': true }).forEach(() => {});
方式3:调用.next()(极简触发)
这是最轻量化的触发方式,只需要获取游标下一个文档(虽然$out不会返回任何文档,但这会触发整个管道执行):
await collection.aggregate(aggregationSteps, { 'allowDiskUse': true }).next();
额外提示
在MongoDB Node.js驱动的v4+版本中,这个行为有了优化,部分场景下聚合会自动执行,但v3.0.6这类旧版本依然需要手动触发游标执行。另外要注意,$out操作本身不会向客户端返回文档,但触发游标执行是让服务器完成整个聚合管道的必要前提。
内容的提问来源于stack exchange,提问作者Matthias Herrmann
相关产品推荐
相关产品推荐

