游标与遍历
本教程共 50 篇 · 第 27 篇 · 更新于 2026-07-30 · 约 7 分钟阅读
27. 游标与遍历
本节目标:理解 find 返回的游标(Cursor)是什么,学会用 forEach 遍历、toArray 转成数组,并了解 batchSize 分批拉取和游标的关闭与耗尽。
你以为 find() 一下就把数据全取回来了?其实不是。它返回的是一个游标(Cursor)——可以理解成「一张还没真正去取的清单」。数据是在你遍历它的时候,分批从服务器拉过来的。
db.users.insertMany([
{ _id: 1, name: "张三", age: 28, city: "北京" },
{ _id: 2, name: "李四", age: 34, city: "上海" },
{ _id: 3, name: "王五", age: 22, city: "北京" },
{ _id: 4, name: "赵六", age: 41, city: "广州" },
{ _id: 5, name: "孙七", age: 30, city: "上海" }
])
游标是「延迟执行」的
find 本身不立刻把文档搬进内存,它只是构建了一个查询计划:
// 这里 cursor 只是一个游标,还没真正读数据
const cursor = db.users.find({ city: "北京" })
只有当你开始遍历、或者显式要结果时,MongoDB 才真正去取数据。这叫「延迟执行(Lazy Evaluation)」。
Note在 mongosh 里直接输入
db.users.find()会打印前 20 条,那是 shell 自动帮你迭代了。但写在脚本里,它始终是个游标对象。
forEach:逐条处理
用 forEach 对每条文档执行回调,适合边遍历边处理:
// 打印每个北京用户的名字
db.users.find({ city: "北京" }).forEach(doc => {
print("用户:" + doc.name)
})
toArray:一次性转成数组
toArray() 把游标里剩下的全部文档拉进一个数组,方便后续当普通数组用:
// 转成数组后就能用数组方法
const arr = db.users.find({ city: "北京" }).toArray()
print("北京用户数:" + arr.length)
Warning
toArray()会把所有结果一次性载入内存。结果很多(上万条)时慎用,容易撑爆客户端内存。大结果集优先用forEach流式处理。
batchSize:控制每次拉多少
游标不是一次拉完,而是按「批次(batch)」从服务器取。默认首批 101 个文档(或 16MB,先到为准)。用 batchSize(n) 调整每批大小:
// 每批只拉 2 条,分多批取完
db.users.find({}).batchSize(2).forEach(doc => print(doc.name))
批次小,网络往返多;批次大,单次内存占用高。一般不用手动调,默认就够。
Tip要限制「总共看多少条」,用
limit(n);要调「每次网络取多少」,才用batchSize(n)。两者作用不同,别混。
主动关闭游标:close()
如果遍历到一半不想读了,可以调 close() 释放游标:
const cursor = db.users.find({})
// ... 处理一部分后决定不读了
cursor.close()
判断是否耗尽:isExhausted()
isExhausted() 返回布尔值,表示游标里的文档是不是已经取完了:
const cursor = db.users.find({ city: "上海" })
while (cursor.hasNext()) {
print(cursor.next().name)
}
print("是否取完:" + cursor.isExhausted())
hasNext() 看还有没有下一条,next() 取当前这条并前进。这是游标最底层的遍历方式。
游标要点回顾
| 方法/概念 | 作用 |
|---|---|
| 游标(Cursor) | find 返回、延迟执行的结果句柄 |
forEach(fn) | 逐条执行回调 |
toArray() | 全部拉进数组(占内存) |
batchSize(n) | 每批网络拉取条数 |
hasNext() / next() | 手动一条条取 |
close() | 提前释放游标 |
isExhausted() | 是否取完 |
Note游标默认有 10 分钟空闲超时(服务端)。如果拿到游标后长时间不遍历,再取可能已失效。一般场景下边查边用,不会碰到。
游标就是 MongoDB 处理「大量结果」的方式。下章我们进入聚合框架,那是另一套更强大的数据处理流水线。