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

从游标访问数据

本页内容

  • 概述
  • 光标范式
  • 异步迭代
  • 手动迭代
  • 返回所有文档的数组
  • 流API
  • 事件API
  • 光标实用方法
  • 重置
  • 关闭

返回多个文档的读取操作不会立即返回所有匹配查询的值。因为一个查询可能匹配非常大的文档集,这些操作返回一个称为光标的对象,该对象引用由查询标识的文档。光标以批量方式检索文档,以减少内存消耗和网络带宽使用。光标高度可配置,并为不同的用例提供多种交互范式。

以下函数直接返回光标:

  • 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() 方法,将其转换为 Node 可读流。这些流在 对象模式 下操作,通过管道传递 JavaScript 对象,而不是缓冲区或字符串。

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

作为可读流,游标也支持事件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();

返回

检索数据