GridFSを使用した大容量のファイルの保存
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")
ファイルのアップロード
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}"))
MongoDB のクエリの詳細については、 データの取得 を参照してください。
ファイルのダウンロード
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ドキュメントを参照してください。