Docs 菜单
Docs 主页
/ / /
Node.js 驱动程序
/ / /

从游标访问数据

在此页面上

  • Overview
  • 游标范例
  • 异步迭代
  • 手动遍历
  • 返回所有文档的数组
  • 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 服务器中的游标资源:

await cursor.close();

您可以使用中止信号取消游标操作。如果不再需要游标使用的内存和网络资源,这可以帮助您通过释放这些资源管理资源。

注意

此功能是实验性的。中止信号会关闭连接,这可能会导致不必要的重新建立连接。

您可以将 signal 命令传递给以下方法:

  • collection.find()

  • collection.findOne()

  • collection.aggregate()

  • collection.countDocuments()

  • db.listCollections()

  • db.command()

要使用中止信号,请创建一个 AbortController实例并从控制器中提取 signal。在此代码示例中,进程侦听 SIGINT (Ctrl+C) 以触发abort() 方法。您可以将 signal 选项传递给 find() 方法,以便在信号触发时中止游标操作,如以下示例所示:

const controller = new AbortController();
const { signal } = controller;
process.on('SIGINT', () => controller.abort(new Error('^C pressed')));
try {
const cursor = myColl.find({}, { signal });
for await (const doc of cursor) {
console.log(doc);
}
} catch (error) {
if (error === signal.reason) {
console.error('Operation aborted:', error);
} else {
console.error('Unexpected error:', error);
}
}

后退

Retrieve Data