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

ファイルを検索する際、GridFS は指定されたバケット内の files コレクションからメタデータを取得し、その情報を使用して chunks コレクション内のドキュメントからファイルを再構築します。ファイルをメモリに読み込んだり、ストリームに出力したりすることもできます。
GridFS バケットの作成
GridFS からファイルを保存または検索するには、 GridFSBucket()コンストラクターを呼び出し、 MongoDatabaseインスタンスを渡して GridFS バケットを作成します。 GridFSBucketインスタンスを使用して、バケット内のファイルの読み取り操作および書込み操作を呼び出すことができます。
val bucket = GridFSBucket(database) 
デフォルト名 fs 以外のカスタム名のバケットを作成または参照には、次の例に示すように、バケット名を 2 番目のパラメータとして GridFSBucket() コンストラクターに渡します。
val filesBucket = GridFSBucket(database, "files") 
Tip
タイムアウト設定
クライアント側の操作タイムアウト(COT)設定を使用して、サーバーがバケットでGridFS操作を完了できる時間を制限できます。GridFSでこの設定を使用する方法の詳細については、「 サーバー実行時間制限ガイド 」の GridFSセクションを参照してください。
ファイルのアップロード
GridFSBucket.uploadFromObservable()メソッドはObservable[ByteBuffer]の内容を読み取り、 GridFSBucketインスタンスに保存します。
GridFSUploadOptionsタイプを使用して、チャンク サイズを構成したり、追加のメタデータを含めたりできます。
次の例では、 Observable[ByteBuffer] の内容を GridFSBucket にアップロードします。
// Get the input stream val observableToUploadFrom = Observable(   Seq(ByteBuffer.wrap("MongoDB Tutorial".getBytes(StandardCharsets.UTF_8))) ) // Create some custom options val options = new GridFSUploadOptions()   .chunkSizeBytes(358400)   .metadata(Document("type" -> "presentation")) // Upload the file val fileIdObservable = filesBucket.uploadFromObservable("mongodb-tutorial", observableToUploadFrom, options) val fileId = Await.result(fileIdObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) println(s"File uploaded with id: ${fileId.toHexString}") 
ファイル情報の検索
このセクションでは、GridFS バケットの files コレクションにストアされているファイル メタデータを検索する方法を学びます。メタデータには、参照先のファイルに関する次のような情報が含まれます。
- ファイルの - _id
- ファイルの名前 
- ファイルの長さ/サイズ 
- アップロード日時 
- その他の情報をストアできる - metadataドキュメント
filesコレクションから取得できるフィールドの詳細については、 MongoDB ServerマニュアルのGridFSファイル コレクション のドキュメントを参照してください。
GridFSバケットからファイルを検索するには、GridFSBucketインスタンスで find() メソッドを呼び出します。 次のコード例では、 GridFSバケット内のすべてのファイルからファイルメタデータを検索して出力します。
val filesObservable = filesBucket.find() val results = Await.result(filesObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) results.foreach(file => println(s" - ${file.getFilename}")) 
ファイルのダウンロード
downloadToObservable()メソッドは、MongoDB からコンテンツを読み取るObservable[ByteBuffer]を返します。
ファイルをファイル_idでダウンロードするには、 _idを メソッドに渡します。 次の例では、ファイルを ファイル_idでダウンロードします。
val downloadObservable = filesBucket.downloadToObservable("<example file ID>") val downloadById = Await.result(downloadObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) 
ファイルの _id がわからないがファイル名がわかっている場合は、ファイル名を downloadToObservable() メソッドに渡すことができます。 次の例では、 mongodb-tutorial という名前のファイルをダウンロードします。
val downloadObservable = filesBucket.downloadToObservable("mongodb-tutorial") val downloadById = Await.result(downloadObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) 
注意
同じ filename 値を持つドキュメントが複数ある場合、 GridFS は指定された名前( uploadDateフィールドによって決定)を持つ最新のファイルを取得します。
ファイル名の変更
バケット内の GridFS ファイルの名前を更新するには、rename() メソッドを使用します。名前を変更するファイルは、ファイル名ではなく、ファイルの _id フィールドで指定する必要があります。
次の例では、ファイルの名前をmongodbTutorialに変更します。
val renameObservable = filesBucket.rename("<example file ID>", "mongodbTutorial") Await.result(renameObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) 
注意
rename()メソッドでサポートされているファイル名の更新は、一度に 1 件のみです。 複数のファイルの名前を変更するには、バケットからファイル名と一致するファイルのリストを検索し、名前を変更するファイルから_idフィールドを抽出し、各値をrename()メソッドに個別に呼び出して渡します。
ファイルの削除
delete() メソッドを使用して、ファイルのコレクションドキュメントと関連するチャンクをバケットから削除します。 削除するファイルは、ファイル名ではなく、_idフィールドで指定する必要があります。
次の例では、 _id でファイルを削除しています。
val deleteObservable = filesBucket.delete("<example file ID>") Await.result(deleteObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) 
注意
delete()メソッドでサポートされているファイルの削除は、一度に 1 件のみです。 複数のファイルを削除するには、バケットからファイルを検索し、削除するファイルから_idフィールドを抽出し、 delete()メソッドを個別に呼び出して各値を渡します。
API ドキュメント
GridFS を使用して大容量のファイルを保存および検索する方法の詳細については、次のAPIドキュメントを参照してください。