首页/数据/NoSQL 速查/游标方法 hasNext / next / toArray
MongoDB99 条

游标方法 hasNext / next / toArray

游标是懒加载结果集:hasNext/next 逐条取,forEach/map 遍历,toArray 一次性读进内存;batchSize 控制每次网络批量。

NoSQL 速查数据更新于 2026-10-13

游标是懒加载的

查询返回的不是结果数组而是游标:数据按批次从服务端取回,客户端逐条消费。hasNext/next 适合边取边处理,toArray 一次性读进内存,batchSize 控制每次网络往返取多少条。理解批次机制很重要——它决定了内存占用与网络往返次数,也是「在命令行里只看到前 20 条」这类现象的来源。

基本信息

逐条遍历while (c.hasNext()) { printjson(c.next()) }
一次取完c.toArray(),结果全部进内存
批量大小c.batchSize(200),控制每次网络取回条数
超时控制c.maxTimeMS(3000)、c.noCursorTimeout()
当前批次剩余c.objsLeftInBatch()
版本提示cursor.count() 已废弃,改用 countDocuments 或 estimatedDocumentCount

典型使用场景

  • 导出与迁移:用游标分批拉取,避免一次性把大结果读进内存
  • 在线批处理:配合 batchSize 与 maxTimeMS 控制单批资源占用
  • 命令行排查:默认只打印首批数据,确认总量必须显式计数
  • 慢查询定位:对游标调用 explain 查看扫描量与批次行为
  • 长时间任务:给游标设置合理超时,任务中断后能被及时发现

四种遍历方式

四种遍历方式
// 逐条:内存占用最小,适合边取边处理
const c = db.logs.find({ level: "error" }).batchSize(200)
while (c.hasNext()) { printjson(c.next()) }

// 一次性取完:只在结果集确定较小、且后续需要随机访问时使用
const arr = db.users.find({ vip: true }).limit(100).toArray()
print(arr.length)

// 回调式遍历:内部仍按批次取数据,写法更紧凑
db.logs.find({ level: "warn" }).forEach(function (doc) { print(doc._id) })

// 确定总量用计数方法,而不是看游标打印出的条数
const n = db.logs.countDocuments({ level: "error" })

方法与行为读法

方法作用注意点
hasNext / next逐条判断与取值遍历期间数据被修改可能影响后续批次
toArray全部读入内存大结果集会造成内存压力甚至进程被终止
batchSize设置每次网络取回条数设得过大单批内存高,过小则往返次数增加
limit / skip限制返回条数与偏移深偏移代价高,顺序翻页更适合键集方式
maxTimeMS限制游标执行时长超时是错误而非空结果,要按错误处理
objsLeftInBatch当前批次剩余条数用于确认批次行为与调试
默认不返回全部数据是设计而非缺陷:命令行打印游标通常只显示前一批文档,需要总数时要显式计数,否则很容易把「只有 20 条」当结论。
toArray 会把结果全量读入客户端内存:导出或统计类任务应逐批处理或直接聚合,不要在大集合上使用。

易错点

  • 把命令行打印的条数当成总数:默认只显示首批数据,误判数据量会导致后续判断全部跑偏
  • 对大结果集调用 toArray:客户端内存被吃满甚至被系统终止,任务中途失败且没有断点
  • 游标遍历期间数据同时被修改:可能重复或遗漏读到的文档,需要快照或按不可变主键排序
  • 忘记游标超时设置:长时间任务下服务端可能回收游标,处理到一半报游标不存在

数据来源与参考

  • MongoDB Manual: Cursor Methods
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌