Overview
このガイドでは、GridFS を使用して MongoDB に大容量ファイルをストア、検索する方法を学びます。GridFS とは、ストレージ時にファイルをチャンクに分割し、検索時にファイルを再アセンブルする方法を記述した仕様です。GridFS のドライバー実装で、ファイル ストレージの操作と組織を管理します。
ファイルのサイズが BSON ドキュメントのサイズ制限である 16 メガバイトを超える場合は、GridFS を使用します。GridFS がユースケースに適しているかどうかの詳細については、GridFS Server のマニュアル ページを参照してください。
GridFS の操作と実装について詳しくは、次のセクションを参照してください。
GridFS の仕組み
GridFS により、ファイルはバケット(ファイルのチャンクと記述情報を含む MongoDB コレクションのグループ)に整理されます。バケットには、GridFS の仕様に定義されている規則を使用して名前付けされた、以下のコレクションが含まれています。
chunksコレクションには、バイナリ ファイルのチャンクがストアされます。filesコレクションには、ファイルのメタデータがストアされます。
新しい GridFS バケットを作成すると、ドライバーはchunks filesコレクションと コレクションを作成し、別の名前を指定しない限り、デフォルトのバケット名fs をプレフィックス付けします。また、ファイルや関連メタデータを効率的に取得できるように、各コレクションにインデックスも作成します。 ドライバーは、GridFS バケットがまだ存在しない場合、最初の書込み操作でのみ GridFS バケットを作成します。 ドライバーは、インデックスが存在しない場合と、バケットが空の場合にのみインデックスを作成します。 GridFS インデックスの詳細については、サーバー マニュアルの「 GridFS インデックス 」のページを参照してください。
GridFS を使用してファイルをストアする場合、ドライバーはファイルを小さな部分に分割し、各ファイルは chunks コレクションに個別のドキュメントとして表されます。また、ユニークなファイル ID、ファイル名、およびその他のファイル メタデータを含むドキュメントを files コレクションに作成します。ファイルをメモリからアップロードすることも、ストリームからアップロードすることもできます。次の図は、GridFS がファイルをバケットにアップロードするときにファイルを分割する方法を示しています。

ファイルを検索する際、GridFS は指定されたバケット内の files コレクションからメタデータを取得し、その情報を使用して chunks コレクション内のドキュメントからファイルを再構築します。ファイルをメモリに読み込んだり、ストリームに出力したりすることもできます。
GridFS バケットの作成
バケットを作成するか、既存のバケットへの参照を取得して、GridFS からのファイルのストアまたは検索を開始します。データベースをパラメータとして渡して、GridFSBucket インスタンスを作成します。その後、GridFSBucket インスタンスを使用して、バケット内のファイルの読み取り操作および書込み (write) 操作を呼び出すことができます。
const db = client.db(dbName); const bucket = new mongodb.GridFSBucket(db);
2 番目のパラメーターとして create() メソッドにバケット名を渡し、次の例に示すように、デフォルト名 fs 以外のカスタム名のバケットを作成または参照します。
const bucket = new mongodb.GridFSBucket(db, { bucketName: 'myCustomBucket' });
詳細については、 GridFSbucket APIドキュメント を参照してください。
ファイルのアップロード
特定のファイル名でアップロード ストリームを作成するには、 GridFSBucketのopenUploadStream()メソッドを使用します。 Node.js 読み取りストリームをアップロード ストリームに接続するには、 pipe()メソッドを使用します。 openUploadStream()メソッドでは、ファイル チャンク サイズやその他のフィールドと値のペアなどの構成情報を指定し、メタデータとして保存できます。
次の例えは、変数fsで表される Node.js 読み取りストリームをGridFSBucketインスタンスのopenUploadStream()メソッドにパイプする方法を示しています。
fs.createReadStream('./myFile'). pipe(bucket.openUploadStream('myFile', { chunkSizeBytes: 1048576, metadata: { field: 'myField', value: 'myValue' } }));
詳細については、OpenUploadStream() APIドキュメント を参照してください。
ファイル情報の検索
このセクションでは、GridFS バケットの files コレクションにストアされているファイル メタデータを検索する方法を学びます。メタデータには、参照先のファイルに関する次のような情報が含まれます。
ファイルの
_idファイルの名前
ファイルの長さ/サイズ
アップロード日時
その他の情報をストアできる
metadataドキュメント
GridFS バケットからファイルを検索するには、GridFSBucket インスタンスの find() メソッドを呼び出します。このメソッドは、結果にアクセスできる FindCursor インスタンスを返します。
次のコード例は、GridFS バケット内のすべてのファイルからファイル メタデータを検索して印刷する方法を示しています。FindCursor イテラブルから検索した結果をトラバースする方法はさまざまありますが、次の例では、for await...of 構文を使用して結果を表示します。
const cursor = bucket.find({}); for await (const doc of cursor) { console.log(doc); }
find() メソッドは、さまざまなクエリ仕様を受け入れ、sort() メソッド、limit() メソッド、project() メソッドなどの他のメソッドと組み合わせることができます。
このセクションで述べられたクラスとメソッドについて詳しくは、次のリソースを参照してください。
ファイルのダウンロード
MongoDB データベースからファイルをダウンロードするには、GridFSBucket の openDownloadStreamByName() メソッドを使用してダウンロード ストリームを作成します。
次の例は、filename フィールドにストアされているファイル名で参照されるファイルを作業ディレクトリにダウンロードする方法を示しています。
bucket.openDownloadStreamByName('myFile'). pipe(fs.createWriteStream('./outputFile'));
注意
同じ filename 値を持つドキュメントが複数ある場合、GridFS は指定された名前(uploadDate フィールドによって決定)を持つ最新のファイルをストリーミングします。
あるいは、ファイルの _id フィールドをパラメータとして受け取る openDownloadStream() メソッドを使用することもできます。
bucket.openDownloadStream(ObjectId("60edece5e06275bf0463aaf3")). pipe(fs.createWriteStream('./outputFile'));
注意
GridFS ストリーミング API は部分的なチャンクを読み込むことはできません。ダウンロード ストリームが MongoDB からチャンクをプルする必要がある場合、チャンク全体をメモリにプルします。通常、255 KB のデフォルトのチャンク サイズで十分ですが、チャンク サイズを小さくしてメモリのオーバーヘッドを減らすことができます。
openDownloadStreamByName() メソッドの詳細については、そのAPIドキュメントを参照してください。
ファイル名の変更
バケット内の GridFS ファイルの名前を更新するには、rename() メソッドを使用します。名前を変更するファイルは、ファイル名ではなく、ファイルの _id フィールドで指定する必要があります。
注意
rename() メソッドでサポートできるファイル名の更新は、一度に 1 件のみです。複数のファイルの名前を変更するには、バケットからファイル名と一致するファイルのリストを検索し、名前を変更するファイルから _id フィールドを抽出し、rename() メソッドを個別に呼び出して各値を渡します。
次の例では、ドキュメントの _id フィールドを参照して filename フィールドを "newFileName" に更新する方法を示しています。
bucket.rename(ObjectId("60edece5e06275bf0463aaf3"), "newFileName");
このメソッドの詳細については、rename() APIドキュメント を参照してください。
ファイルの削除
バケットからファイルを削除するには、delete() メソッドを使用します。削除するファイルは、ファイル名ではなく、_id フィールドで指定する必要があります。
注意
delete() メソッドでサポートできるファイルの削除は、一度に 1 件のみです。複数のファイルを削除するには、バケットからファイルを検索し、削除するファイルから _id フィールドを抽出し、delete() メソッドを個別に呼び出して各値を渡します。
次の例は、_id フィールドを参照してファイルを削除する方法を示しています。
bucket.delete(ObjectId("60edece5e06275bf0463aaf3"));
このメソッドについて詳しくは、「delete() API ドキュメント」を参照してください。
GridFS バケットの削除
drop() メソッドを使用してバケットの files コレクションと chunks コレクションを排除すると、実質的にバケットが削除されます。次のコード例は、GridFS バケットを削除する方法を示しています。
bucket.drop();
このメソッドの詳細については、 drop() APIドキュメントを参照してください。