でのカーソルの反復 mongosh
db.collection.find()
メソッドはカーソルを返します。 ドキュメントにアクセスするには、カーソルを反復する必要があります。 ただし、 mongosh
では、返されたカーソルがvar
キーワードを使用して変数に割り当てられていない場合、カーソルは自動的に最大20回まで反復されます[ 1 ]が最初の まで出力します。結果の20ドキュメント:
次の例で、カーソルを手動で反復処理してドキュメントにアクセスする方法や、イテレータ インデックスを使用する方法を説明します。
カーソルの手動反復処理
mongosh
では、 find()
メソッドから返されたカーソルを var
キーワードを使用して変数に割り当てると、カーソルは自動的に反復されません。
以下の例のように、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()
ヘルパー メソッドを使用して 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];
カーソルの動作
セッション内で開かれたカーソル
MongoDB 5.0 以降では、対応する クライアント セッション 内で作成されたカーソルは、セッションがタイムアウトした場合、またはクライアントがカーソルを使い果たした場合に、対応する サーバー セッション が killSessions
コマンドで終了すると閉じます。
デフォルトでは、サーバー セッションの有効期限は 30 分です。この値を変更するには、mongod
の起動時に localLogicalSessionTimeoutMinutes
パラメータを設定します
セッション外で開かれたカーソル
セッション中に開かれていないカーソルは、 10分間操作がない場合、またはクライアントがカーソルを使い切ると自動的に閉じます。 mongosh
でこの動作をオーバーライドするには、 cursor.noCursorTimeout()
メソッドを使用します。
var myCursor = db.users.find().noCursorTimeout();
noCursorTimeout
オプションの設定後は、cursor.close()
を使用してカーソルを手動で閉じるか、カーソルの結果を使い切って閉じる必要があります。
noCursorTimeout
オプションの設定について詳しくは、ドライバーのドキュメント を参照してください。
カーソルの分離
カーソルによってドキュメントが返されると、他の操作がクエリとインターリーブする可能性があります。
カーソル バッチ
MongoDB サーバーはクエリ結果をバッチで返します。バッチ内のデータ量は、BSON ドキュメントの最大サイズ以下です。バッチのデフォルト サイズをオーバーライドするには、batchSize()
および limit()
を参照してください。
find()
、aggregate()
、listIndexes
、listCollections
の各タイプの操作により、バッチするごとに最大 16 MB のデータが返されます。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> } }