Access Data From a Cursor从游标访问数据¶
On this page
Overview概述¶
Read operations that return multiple documents do not immediately return all values matching the query. 返回多个文档的读取操作不会立即返回与查询匹配的所有值。Because a query can potentially match very large sets of documents, these operations rely upon an object called a cursor. 因为查询可能会匹配非常大的文档集,所以这些操作依赖于称为游标的对象。A cursor fetches documents in batches to reduce both memory consumption and network bandwidth usage. 游标可以批量获取文档,以减少内存消耗和网络带宽使用。Cursors are highly configurable and offer multiple interaction paradigms for different use cases.游标是高度可配置的,并为不同的用例提供多种交互范例。
The following functions directly return cursors:以下函数直接返回游标:
Collection.find()
Collection.aggregate()
Collection.listIndexes()
Db.aggregate()
Db.listCollections()
Other methods such as Collection.findOne() and Collection.watch() use cursors internally, and return the results of the operations instead of a cursor.其他方法,如Collection.findOne()
和Collection.watch()
在内部使用游标,并返回操作结果而不是游标。
Cursor Paradigms光标范例¶
You can work with cursors using a number of cursor paradigms. 您可以使用许多游标范例来使用游标。Most cursor paradigms allow you to access query results one document at a time, abstracting away network and caching logic. 大多数游标范例允许您一次访问一个文档的查询结果,从而抽象出网络和缓存逻辑。However, since use cases differ, other paradigms offer different access patterns, like pulling all matching documents into a collection in process memory.然而,由于用例不同,其他范例提供了不同的访问模式,比如将所有匹配的文档拉入进程内存中的集合。
Do not combine different cursor paradigms on a single cursor. 不要在单个游标上组合不同的游标范例。Operations such as hasNext()
, forEach()
, and toArray()
each predictably modify the original cursor. hasNext()
、forEach()
和toArray()
等操作都可以预测地修改原始光标。If you mix these calls on a single cursor, you may receive unexpected results.如果在单个游标上混合使用这些调用,可能会收到意外的结果。
Because asynchronous calls directly modify the cursor, executing asynchronous calls on a single cursor simultaneously can also cause undefined behaviour. 由于异步调用直接修改游标,因此同时对单个游标执行异步调用也可能导致未定义的行为。Always wait for the previous asynchronous operation to complete before running another.在运行另一个异步操作之前,请始终等待上一个异步操作完成。
When you reach the last result through iteration or through an at-once fetch, the cursor is exhausted which means it ceases to respond to methods that access the results.当您通过迭代或一次性获取到达最后一个结果时,游标将耗尽,这意味着它将停止响应访问结果的方法。
For Each Functional IterationForEach函数迭代¶
You can pass a function to the forEach() method of any cursor to iterate through results in a functional style:可以将函数传递给任何游标的forEach()
方法,以函数样式迭代结果:
const cursor = collection.find({});
await cursor.forEach(doc=> console.log(doc));
Return an Array of All Documents返回所有文档的数组¶
For use cases that require all documents matched by a query to be held in memory at the same time, use toArray(). 对于要求查询匹配的所有文档同时保存在内存中的用例,请使用toArray()
。Note that large numbers of matched documents can cause performance issues or failures if the operation exceeds memory constraints. 请注意,如果操作超出内存限制,大量匹配的文档可能会导致性能问题或失败。Consider using forEach() to iterate through results unless you want to return all documents at once.考虑使用forEach()
来遍历结果,除非您想同时返回所有文档。
const cursor = collection.find({});
const allValues = await cursor.toArray();
Asynchronous Iteration异步迭代¶
Cursors implement the AsyncIterator interface, which allows you to use cursors in 游标实现for ... await
loops:AsyncIterator
接口,该接口允许您在for ... await
循环中使用游标:
const cursor = collection.find({});
console.log("async");
for await (const doc of cursor) {
console.log(doc);
}
Manual Iteration人工迭代¶
You can use the hasNext() method to check if a cursor can provide additional data, and then use the next() method to retrieve the subsequent element of the cursor:可以使用hasNext()
方法检查游标是否可以提供其他数据,然后使用next()
方法检索游标的后续元素:
const cursor = collection.find({});
while (await cursor.hasNext()) {
console.log(await cursor.next());
}
Stream API¶
Cursors expose the 游标公开stream()
method to convert them to Node Readable Streams. stream()
方法以将其转换为节点可读的流。These streams operate in Object Mode, which passes JavaScript objects rather than Buffers or Strings through the pipeline.这些流以对象模式运行,对象模式通过管道传递JavaScript对象而不是缓冲区或字符串。
const cursor = collection.find({});
cursor.stream().on("data", doc=> console.log(doc));
Event API¶
As Readable Streams, cursors also support the Event API's 作为可读流,游标还支持事件API的close
, data
, end
and readable
events:close
、data
、end
和readable
事件:
const cursor = collection.find({});
// the "data" event is fired once per document每个文档触发一次“data”事件
cursor.on("data", data=> console.log(data));
Cursor Utility Methods游标实用程序方法¶
Count¶
For an estimated count of the number of documents referenced by the cursor, use count():有关光标引用的文档数的估计计数,请使用count()
:
const cursor = collection.find({});
const count = await cursor.count();
Rewind¶
To reset a cursor to its initial position in the set of returned documents, use rewind().要将光标重置为其在返回文档集中的初始位置,请使用rewind()
。
const cursor = collection.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);
Close¶
Cursors consume memory and network resources both in the client application and in the connected instance of MongoDB. 游标消耗客户端应用程序和连接的MongoDB实例中的内存和网络资源。Use close() to free up a cursor's resources in both the client application and the MongoDB server:使用close()
释放客户端应用程序和MongoDB服务器中的游标资源:
await cursor.close();