“文档” 菜单
文档首页
/ / /
Node.js 驱动程序
/ / /

从游标访问数据

在此页面上

  • 概述
  • 游标范例
  • 异步迭代
  • 手动遍历
  • 返回所有文档的数组
  • Stream API
  • 事件 API
  • 游标实用程序方法
  • Rewind
  • 关闭

返回多个文档的读取操作不会立即返回与查询匹配的所有值。由于查询可能匹配数量极大的文档集,因此这些操作会返回一个称为游标的对象,该对象会引用查询所标识的文档。游标会分批获取文档,以减少内存消耗和网络带宽占用。游标具有高度可配置性,并为不同的使用案例提供多种交互范例。

以下函数会直接返回游标:

  • Collection.find()

  • Collection.aggregate()

  • Collection.listIndexes()

  • Collection.listSearchIndexes()

  • Db.aggregate()

  • Db.listCollections()

其他方法(例如 Collection.findOne()Collection.watch())在内部使用游标,并返回操作结果而不是游标。

您可以使用几种不同的游标范例来访问数据。大多数游标范例允许一次访问一个文档的查询结果,对网络和缓存逻辑抽象化。然而,由于使用案例不同,其他范例会提供不同的访问模式,例如将所有匹配的文档拉入进程内存中的集合。

警告

不要在单个游标上组合不同的游标范例。不要在单个游标上组合不同的游标范例。对于 hasNext()toArray() 等操作,每个操作都会对原始游标进行可预测的修改。如果您在单个游标上结合使用这些调用,您可能会收到意外的结果。

警告

由于异步调用会直接修改游标,因此在同一个游标上同时执行多个异步调用会导致未定义的行为。请始终等待前一个异步操作完成后,再执行下一个异步操作。

注意

当您通过迭代或者一次性获取所有文档的操作到达最后一个结果时,游标将被耗尽,这意味着它将不再响应试图访问结果的方法。

游标实现 AsyncIterator 接口,该接口可允许您在 for await...of 循环中使用游标:

const cursor = myColl.find({});
console.log("async");
for await (const doc of cursor) {
console.log(doc);
}

您可以使用 hasNext() 方法检查游标能否检索更多数据,然后使用 next() 方法检索游标的后续元素:

const cursor = myColl.find({});
while (await cursor.hasNext()) {
console.log(await cursor.next());
}

对于要求将查询匹配到的所有文档同时保存在内存中的使用案例,请使用 toArray() 方法。请注意,如果操作超出内存限制,大量匹配的文档可导致性能问题或故障。请考虑使用 for await...of 语法来遍历结果,而不是一次性返回所有文档。

const cursor = myColl.find({});
const allValues = await cursor.toArray();

游标会公开 stream() 方法以将其转换为节点可读流。这些流在对象模式下运行,该模式通过管道传递 JavaScript 对象,而不是传递缓冲区或字符串。

const cursor = myColl.find({});
cursor.stream().on("data", doc => console.log(doc));

作为可读流,游标还支持 Event API 的 closedataendreadable 事件:

const cursor = myColl.find({});
// the "data" event is fired once per document
cursor.on("data", data => console.log(data));

要将游标重置为所返回文档集中的初始位置,请使用 rewind()。

const cursor = myColl.find({});
const firstResult = await cursor.toArray();
console.log("First count: " + firstResult.length);
await cursor.rewind();
const secondResult = await cursor.toArray();
console.log("Second count: " + secondResult.length);

游标会消耗客户端应用程序和已连接 MongoDB 实例中的内存和网络资源。使用 close() 在客户端应用程序和 MongoDB Server 中释放游标的资源:

await cursor.close();
← 检索数据