Overview
このガイドでは、変更ストリームを使用してデータベースへのリアルタイムの変更を監視する方法を学習できます。 変更ストリームは、アプリケーションがコレクション、データベース、または配置のデータ変更をサブスクライブできる MongoDB Server の機能です。
Tip
Atlas Stream Processing
変更ストリームの代わりに、Atlas Stream Processing を使用してデータのストリームを処理および変換できます。データベースイベントのみを登録する変更ストリームとは異なり、Atlas Stream Processing は複数のデータイベント型を管理し、拡張データプロセシング機能を提供します。この機能の詳細については、 MongoDB AtlasドキュメントのAtlas Stream Processingを参照してください。
変更ストリームを開く
次のオブジェクトのwatch()メソッドを使用して、MongoDB の変更を監視できます。
各オブジェクトに対して、 watch()メソッドは変更ストリームを開き、変更が発生したときに変更イベントドキュメントを発行します。
オプションとして、watch() メソッドは複数の集約ステージの配列で構成される集約パイプラインを最初のパラメーターとして取ることができます。集計ステージでは、変更イベントをフィルタリングして変換します。
次のスニペットでは、$match ステージで runtime の値が 15 未満のすべての変更イベントドキュメントが照合され、その他のドキュメントがすべて除外されます。
const pipeline = [ { $match: { runtime: { $lt: 15 } } } ];const changeStream = myColl.watch(pipeline);watch()メソッドは、2 番目のパラメーターとしてoptionsオブジェクトを受け入れます。このオブジェクトで構成できる設定の詳細については、このセクションの最後にあるリンクを参照してください。
watch() メソッドは ChangeStream のインスタンスを返します。変更ストリームを反復処理したり、イベントをリスニングしたりすることで、変更ストリームからイベントを読み取ることができます。
警告
EventEmitter モードと Iterator モードでのChangeStreamの使用は、ドライバーでサポートされていないため、エラーが発生します。これは、ドキュメントを最初に受け取るコンシューマーをドライバー側で保証できない場合の未定義の動作を防ぐためのものです。
変更ストリームからイベントを読み取る方法を示すタブを選択します。
バージョン 4.12 以降、 ChangeStreamオブジェクトは非同期反復可能オブジェクトになります。この変更により、 for-awaitループを使用して、開いている変更ストリームからイベントを取得できるようになります。
for await (const change of changeStream) { console.log("Received change: ", change);}次のようなChangeStreamオブジェクト上のメソッドを呼び出すことができます。
hasNext()ストリーム内の残りのドキュメントを確認するnext()ストリーム内の次のドキュメントをリクエストするclose()ChangeStream を閉じる
on() メソッドを呼び出すことによって、ChangeStream オブジェクトに listner 関数をアタッチできます。このメソッドは、Javascript EventEmitter クラスから継承されます。以下のように、最初のパラメーターとして文字列 "change" を渡し、2 番目のパラメーターとしてリスナー関数を渡します。
changeStream.on("change", (changeEvent) => { /* your listener function */ });リスナー関数は、 changeイベントが発生したときにトリガーされます。変更イベント ドキュメントを受信時に処理するよう、リスナー内でロジックを指定できます。
pause()を呼び出してイベントの発行を停止するか、 resume()呼び出してイベントの発行を継続することで、変更ストリームを制御できます。
変更イベントの処理を停止するには、ChangeStreamインスタンスで close() メソッドを呼び出します。これにより、変更ストリームが閉じられ、リソースが解放されます。
changeStream.close();例
反復
注意
この例を使ってMongoDBのインスタンスに接続し、サンプルデータを含むデータベースとやり取りできます。MongoDBインスタンスへの接続とサンプルデータセットの読み込みの詳細については、 Node.jsドライバーを使い始める ガイドを参照してください。
注意
Typescript固有の機能はありません
次のコード例ではJavaScriptを使用します。このユースケースに関連するドライバーのTypescript固有の機能はありません。
次の例ではinsertDBデータベースのhaikusコレクションの変更ストリームがオープンされ、変更イベントが発生に応じて出力されます。
// Watch for changes in a collection by using a change streamimport { MongoClient } from "mongodb";
// Replace the uri string with your MongoDB deployment's connection string.const uri = "<connection string uri>";
const client = new MongoClient(uri);
// Declare a variable to hold the change streamlet changeStream;
// Define an asynchronous function to manage the change streamasync function run() { try { const database = client.db("insertDB"); const haikus = database.collection("haikus");
// Open a Change Stream on the "haikus" collection changeStream = haikus.watch();
// Print change events as they occur for await (const change of changeStream) { console.log("Received change:\n", change); } // Close the change stream when done await changeStream.close(); } finally { // Close the MongoDB client connection await client.close(); }}run().catch(console.dir);Tip
明示的なリソース管理
Node.jsドライバーは、MongoClient、ClientSession、ChangeStreams、およびカーソルの明示的なリソース管理をネイティブでサポートしています。この機能は実験的なものであり、変更される可能性があります。明示的なリソース管理を使用する方法については、v6.9 リリースノートを参照してください。
このコードを実行してから、挿入または削除操作の実行など、 haikusコレクションに変更を加えると、変更イベント ドキュメントがターミナルに出力されます。
たとえば、コレクションにドキュメントを挿入すると、コードによって次の内容が出力されます。
Received change:{ _id: { _data: '...' }, operationType: 'insert', clusterTime: new Timestamp({ t: 1675800603, i: 31 }), fullDocument: { _id: new ObjectId("..."), ... }, ns: { db: 'insertDB', coll: 'haikus' }, documentKey: { _id: new ObjectId("...") }}注意
更新から完全なドキュメントを受け取る
アップデート操作に関する情報を含む変更イベントは、デフォルトではアップデートされたドキュメント全体ではなく、変更されたフィールドのみを返します。次のように、オプションオブジェクトの fullDocument フィールドを "updateLookup" に設定することで、ドキュメントの最新バージョンも返すように変更ストリームを設定できます。
const options = { fullDocument: "updateLookup" };// This could be any pipeline.const pipeline = [];
const changeStream = myColl.watch(pipeline, options);リスナー関数
次の例では、 insertDBデータベースのhaikusコレクションの変更ストリームを開きます。コレクションで発生する変更イベントを受信して出力するリスナー関数を作成します。
まず、コレクションで変更ストリームを開き、on() メソッドを使用して、変更ストリーム上でリスナーを定義します。リスナーを設定したら、コレクションに対する変更を実行して変更イベントを生成します。
コレクション上で変更イベントを生成するために、insertOne() メソッドを使用して新しいドキュメントを追加します。insertOne() がリスナー関数の登録より先に実行される可能性があるため、simulateAsyncPause と定義したタイマーを使用し、1 秒間待ってから挿入を実行します。
また、ドキュメント挿入後に simulateAsyncPause も使用します。これにより、close() メソッドによって ChangeStream インスタンスが閉じる前に、リスナー関数が変更イベントを受け取って処理を完了するための十分な時間を確保できます。
注意
タイマーを使用する理由
この例で使用されているタイマーは、あくまでもデモンストレーションのためのものです。これにより、リスナーの登録と、終了前のリスナーによる変更イベントの処理に十分な時間を確保できます。
注意
Typescript固有の機能はありません
次のコード例ではJavaScriptを使用します。このユースケースに関連するドライバーのTypescript固有の機能はありません。
/* Change stream listener */
import { MongoClient } from "mongodb";
// Replace the uri string with your MongoDB deployment's connection stringconst uri = "<connection string uri>";
const client = new MongoClient(uri);
const simulateAsyncPause = () => new Promise(resolve => { setTimeout(() => resolve(), 1000); });
let changeStream;async function run() { try { const database = client.db("insertDB"); const haikus = database.collection("haikus");
// Open a Change Stream on the "haikus" collection changeStream = haikus.watch();
// Set up a change stream listener when change events are emitted changeStream.on("change", next => { // Print any change event console.log("received a change to the collection: \t", next); });
// Pause before inserting a document await simulateAsyncPause();
// Insert a new document into the collection await myColl.insertOne({ title: "Record of a Shriveled Datum", content: "No bytes, no problem. Just insert a document, in MongoDB", });
// Pause before closing the change stream await simulateAsyncPause();
// Close the change stream and print a message to the console when it is closed await changeStream.close(); console.log("closed the change stream"); } finally { // Close the database connection on completion or error await client.close(); }}run().catch(console.dir);このページで説明されているクラスとメソッドの詳細については、次のリソースを参照してください。