You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用mongosh的cursor.forEach()时,能否获取元素迭代索引?

MongoDB游标forEach无法获取迭代序号的解决方法

问题背景

习惯使用ES5数组的array.forEach((elem, i) => ...)语法获取元素索引,但MongoDB游标(Cursor)的forEach()方法并不支持传入索引参数——游标并非数组,官方文档对该方法的说明也较为简略。已知可以通过cursor.toArray().forEach()实现,但担心该方式会将所有文档加载到内存,导致性能下降,属于多余步骤。

测试代码(无输出):

db.collection.find().forEach((doc, i) => {
  if ((i == 0) || (i % 50 == 0)) {
    console.log(`we are here: ${i}`); // 无任何输出
  }
})

解决方案

MongoDB的cursor.forEach()确实没有内置传递迭代序号的机制,以下是两种无需转换为数组的高效解决方案:

1. 手动维护计数器

这是最简单直接的方案,遍历前初始化一个计数器变量,每次迭代时更新并使用它,不会产生额外性能开销:

let index = 0;
db.collection.find().forEach((doc) => {
  if (index === 0 || index % 50 === 0) {
    console.log(`we are here: ${index}`);
  }
  index++;
});

2. 使用聚合查询生成序号(MongoDB 4.4+)

如果需要将序号作为文档的一部分处理,可以利用MongoDB 4.4新增的$setWindowFields聚合阶段,结合$documentNumber操作符在查询阶段直接为每个文档生成全局序号,之后遍历游标时直接读取该字段:

db.collection.aggregate([
  {
    $setWindowFields: {
      partitionBy: {}, // 不分区,对所有文档全局计数
      sortBy: { _id: 1 }, // 指定排序字段,保证序号顺序稳定
      output: {
        index: { $documentNumber: {} } // 生成从1开始的序号
      }
    }
  }
]).forEach((doc) => {
  // 注意$documentNumber从1开始,所以判断条件调整为index === 1或index%50===0
  if (doc.index === 1 || doc.index % 50 === 0) {
    console.log(`we are here: ${doc.index}`);
  }
});

方案对比

  • 手动计数器:零额外开销,实现简单,适合仅在遍历过程中需要序号的场景。
  • 聚合生成序号:适合需要将序号与文档绑定的场景,但依赖MongoDB 4.4及以上版本,且会增加聚合查询的少量开销。

内容的提问来源于stack exchange,提问作者amota

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 23:50:34