在 mongo Shell 中迭代游标

在本页面

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

以下示例描述了手动迭代游标以访问文档或使用迭代器索引的方法。

手动迭代游标

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

您可以在 Shell 程序中调用 cursor 变量以最多进行 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() helper 方法来代替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 游标方法和您的driver文档。

[1]*(12)*您可以使用DBQuery.shellBatchSize更改默认值20的迭代次数。有关更多信息,请参见使用 mongo Shell

Iterator Index

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

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

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

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

考虑以下示例:

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

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

myCursor.toArray() [1];

Cursor Behaviors

关闭无效的游标

默认情况下,服务器将在闲置 10 分钟后或 Client 端用尽光标后自动关闭光标。要在mongo shell 中覆盖此行为,可以使用cursor.noCursorTimeout()方法:

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

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

有关设置noCursorTimeout选项的信息,请参见driver文档。

Cursor Isolation

当游标返回文档时,其他操作可能会与查询交错。对于MMAPv1存储引擎,对文档进行干预的写操作可能会导致游标返回一个文档(如果该文档已更改)不止一次。要处理这种情况,请参阅Cursor Snapshot上的信息。

Cursor Batches

MongoDB 服务器批量返回查询结果。批次中的数据量不会超过BSON 文档的最大大小。要覆盖批次的默认大小,请参见batchSize()limit()

3.4 版中的新功能: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();

Cursor Information

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>
   }
}