Docs Menu

カーソルからデータにアクセスする

複数のドキュメントを返す読み取り操作では、クエリに一致するすべての値がすぐに返されるわけではありません。クエリは非常に大きなドキュメントセットと一致する可能性があるため、これらの操作はカーソルと呼ばれるオブジェクトを返します。カーソルは、クエリで識別されたドキュメントを参照します。カーソルはドキュメントをバッチで取得して、メモリ消費とネットワーク帯域幅使用量の両方を削減します。カーソルは高度な構成が可能で、さまざまなユースケースに対応する複数のインタラクションパラダイムを提供します。

次の関数を使用することで、カーソルを直接返せます。

  • Collection.find()

  • Collection.aggregate()

  • Collection.listIndexes()

  • Collection.listSearchIndexes()

  • Db.aggregate()

  • Db.listCollections()

Collection.findOne()Collection.watch() などの他のメソッドでは、内部的にカーソルが使用され、カーソルの代わりに操作の結果が返されます。

データへのアクセスには、いくつかの異なるカーソル パラダイムを使用できます。ほとんどのカーソル パラダイムでは、一度に 1 ドキュメントずつクエリ結果にアクセスできるため、ネットワークとキャッシュ ロジックが抽象化されます。ただし、ユースケースは異なるため、一致するドキュメントをすべてプロセスメモリ内のコレクションに取り込むなど、他のパラダイムではアクセス パターンが異なります。

警告

1 つのカーソル上で異なるカーソル パラダイムを組み合わせないでください。hasNext()toArray() などの操作はそれぞれ、元のカーソルを予想どおりに変更します。これらの呼び出しを 1 つのカーソルで混在させると、予期しない結果が生じる可能性があります。

警告

非同期呼び出しはカーソルを直接変更するため、1 つのカーソルで非同期呼び出しを同時に実行すると、未定義の動作が発生する可能性もあります。必ず前の非同期操作が完了するのを待ってから、次の非同期操作を実行してください。

注意

反復処理または一括フェッチによって最後の結果に到達すると、カーソルが使い果たされ、結果にアクセスするメソッドに応答しなくなります。

カーソルは 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() メソッドを公開します。これらのストリームは オブジェクト モードで 動作し、バッファーや文字列ではなく JavaScript オブジェクトをパイプラインに渡します。

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

読み取り可能なストリームとして、カーソルは Event API の closedataend、および readable イベントもサポートしています。

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();

中止シグナル を使用してカーソル操作をキャンセルすることができます。これにより、カーソルが使用していたメモリやネットワークリソースが不要になった場合に解放され、リソースを管理しやすくなります。

注意

この機能は実験的です。シグナルを中止すると接続が閉じられ、不要な接続の再確立が発生する可能性があります。

あなたは signal コマンドを次のメソッドに渡すことができます。

  • collection.find()

  • collection.findOne()

  • collection.aggregate()

  • collection.countDocuments()

  • db.listCollections()

  • db.command()

中止信号を使用するには、AbortControllerインスタンスを作成し、コントローラーからsignalを抽出します。このコード例では、プロセスは SIGINTCtrl+C)をリッスンして abort() メソッドをtriggerします。シグナルがトリガーされた場合にカーソル操作を中止するには、signal オプションを find() メソッドに渡すことができます。次の例に示すように:

const controller = new AbortController();
const { signal } = controller;
process.on('SIGINT', () => controller.abort(new Error('^C pressed')));
try {
const cursor = myColl.find({}, { signal });
for await (const doc of cursor) {
console.log(doc);
}
} catch (error) {
if (error === signal.reason) {
console.error('Operation aborted:', error);
} else {
console.error('Unexpected error:', error);
}
}