Docs 菜单

Docs 主页开发应用程序MongoDB Manual

在 mongosh 中迭代游标 mongosh

在此页面上

  • 手动遍历游标
  • 迭代器索引
  • 游标行为
  • 游标信息

db.collection.find()方法返回一个游标。要访问文档,需要迭代游标。但是,在 mongosh中,如果返回的游标未使用var关键字赋值给变量,则游标会自动迭代最多20次[ 1 ] ,以打印至第一个结果中的20文档。

以下示例描述了如何通过手动迭代游标,或使用迭代器索引以访问文档。

mongosh中,当您使用var关键字将从find()方法返回的游标分配给变量时,游标不会自动迭代。

可以在 shell 中调用游标变量来迭代多达 20 次 [1] 并打印匹配文档,如以下示例所示:

var myCursor = db.users.find( { type: 2 } );
myCursor

也可以使用游标方法 next() 访问文档,如下例所示:

var myCursor = db.users.find( { type: 2 } );
while (myCursor.hasNext()) {
print(tojson(myCursor.next()));
}

可以考虑使用 printjson() 辅助方法来替换 print(tojson()),作为替代打印操作:

var myCursor = db.users.find( { type: 2 } );
while (myCursor.hasNext()) {
printjson(myCursor.next());
}

可以使用游标方法 forEach() 来迭代游标并访问文档,如以下示例所示:

var myCursor = db.users.find( { type: 2 } );
myCursor.forEach(printjson);

有关游标方法的更多信息,请参阅JavaScript 游标方法驱动程序文档。

[1]( 1, 2 )您可以通过设置 DBQuery.shellBatchSize 属性对文档数量(默认值为 20)进行更改。

mongosh中,您可以使用toArray()方法迭代游标并以数组形式返回文档,如下所示:

var myCursor = db.inventory.find( { type: 2 } );
var documentArray = myCursor.toArray();
var myDocument = documentArray[3];

toArray() 方法会将游标返回的所有文档加载到 RAM 中;toArray() 方法会耗尽游标。

此外,某些驱动程序通过使用游标上的索引(即cursor[index] )来提供对文档的访问。这是首先调用toArray()方法,然后在结果数组上使用索引的快捷方式。

考虑以下示例:

var myCursor = db.users.find( { type: 2 } );
var myDocument = myCursor[1];

myCursor[1] 等效于以下示例:

myCursor.toArray() [1];

从 MongoDB5 开始。0 ,如果相应的 服务器会话 killSessions以 命令结束、会话超时或者客户端已耗尽游标,则在客户 端会话 中创建的游标将关闭。

默认情况下,服务器会话的超时时间为 30 分钟。要更改数值,请在启动 mongod 时设置 localLogicalSessionTimeoutMinutes 参数。

会话下未打开的游标会在10分钟不活动后或客户端耗尽游标后自动关闭。要在mongosh中覆盖此行为,可以使用cursor.noCursorTimeout()方法:

var myCursor = db.users.find().noCursorTimeout();

设置 noCursorTimeout 选项后,必须使用 cursor.close() 手动关闭游标,或者用尽游标的结果。

有关设置noCursorTimeout选项的信息,请参阅驱动程序文档。

当游标返回文档时,其他操作可能会与查询交错进行。

MongoDB Server 分批次返回查询结果。批次中的数据量不会超过 BSON 文档的最大大小。要重写批次的默认大小,请参阅 batchSize()limit()

find()aggregate()listIndexeslistCollections 类型的操作每批次最多返回 16 兆字节。batchSize() 可以执行较小的限制,不能执行较大的限制。

find() 默认情况下,aggregate() 操作的初始批次大小为 101 份文档。针对生成的游标发出的后续 getMore 操作没有默认批量大小,因此它们需满足 16 MB 消息大小的限制。

对于包含不带索引的排序操作的查询,服务器必须在返回任何结果之前将所有文档加载到内存中以执行排序。

当您遍历游标并到达返回批次的末尾时,如果有更多结果,cursor.next() 将执行 getMore operation 来检索下个批次。要查看在迭代游标时批次中还有多少文档,可以使用 objsLeftInBatch() 方法,如以下示例所示:

var myCursor = db.inventory.find();
var myFirstDocument = myCursor.hasNext() ? myCursor.next() : null;
myCursor.objsLeftInBatch();

db.serverStatus() 方法返回一份包含 metrics 字段的文档。metrics 字段包含一个 metrics.cursor 字段,后者包含以下信息:

  • 自上次服务器重启以来超时的游标数量

  • 打开的游标数量,其选项 DBQuery.Option.noTimeout 设置为防止在一段时间不活动后出现超时

  • “固定”打开游标的数量

  • 打开的游标总数

以下示例调用了 db.serverStatus() 方法,并访问了结果中的 metrics 字段,然后通过 metrics 字段访问 cursor 字段:

db.serverStatus().metrics.cursor

结果为以下文档:

{
"timedOut" : <number>
"open" : {
"noTimeout" : <number>,
"pinned" : <number>,
"total" : <number>
}
}

提示

另请参阅:

← 执行长期运行的快照查询