Docs Menu

GridFS

このガイドでは、 GridFS仕様を使用して MongoDB に大容量ファイルを保存、検索する方法を学びます。 GridFS は大きなファイルをチャンクに分割し、各チャンクを別々のドキュメントとして保存します。 GridFS でファイルをクエリすると、ドライバーは必要に応じてチャンクをアセンブルします。 GridFS のドライバー実装は、ファイル ストレージの操作と組織を管理する抽象化です。

ファイルのサイズがBSONドキュメントサイズ制限の 16 MB を超える場合は、 GridFSを使用します。 GridFS は、ファイル全体をメモリにロードせずにファイルにアクセスするのにも役立ちます。 GridFSがユースケースに適しているかどうかの詳細については、サーバー マニュアルの「 GridFS 」を参照してください。

GridFS により、ファイルはバケット(ファイルのチャンクとそれを説明する情報を含む MongoDB コレクションのグループ)に整理されます。 バケットには以下のコレクションが含まれています。

  • chunksはバイナリ ファイル チャンクを保存します

  • filesは、ファイルのメタデータを保存します

新しい GridFS バケットを作成すると、ドライバーによって前述のコレクションが作成されます。 別のバケット名を指定しない限り、コレクション名の前にデフォルトのバケット名fsがコレクション名の前に付きます。 ドライバーは最初の書込み (write) 操作中に新しい GridFS バケットを作成します。

また、ファイルや関連メタデータを効率的に取得できるように、各コレクションにインデックスも作成します。 ドライバーは、インデックスがまだ存在しない場合、およびバケットが空の場合にインデックスを作成します。 GridFSインデックスの詳細については、サーバー マニュアルの「 GridFSインデックス 」を参照してください。

GridFS を使用してファイルを保存する場合、ドライバーはファイルを小さなチャンクに分割し、各ファイルはchunksコレクションに個別のドキュメントとして表されます。 また、ファイル ID、ファイル名、およびその他のファイル メタデータを含むドキュメントをfilesコレクションに作成します。 次の図は、GridFS がアップロードされたファイルを分割する方法を示しています。

A diagram that shows how GridFS uploads a file to a bucket

ファイルを検索する際、GridFS は指定されたバケット内のfilesコレクションからメタデータを取得し、その情報を使用してchunksコレクション内のドキュメントからファイルを再構築します。 ファイルをメモリに読み込んだり、ストリームに出力したりすることもできます。

次のセクションでは、GridFS 操作の実行方法について説明します。

GridFS からファイルを保存または検索するには、バケットを作成するか、MongoDB database 上の既存のバケットへの参照を取得します。 GridFSBucketインスタンスを作成するには、次のコードに示すように、 DatabaseインスタンスでGridFSBucket()メソッドを呼び出します。

db := client.Database("myDB")
bucket := db.GridFSBucket()

注意

GridFS バケットがすでに存在する場合、 GridFSBucket()メソッドは新しいバケットをインスタンス化するのではなく、バケットへの参照を返します。

デフォルトでは、ドライバーはバケットの名前をfsに設定します。 カスタム名のバケットを作成するには、次のコードに示すように、 BucketOptionsインスタンスでSetName()メソッドを呼び出します。

db := client.Database("myDB")
bucketOpts := options.GridFSBucket().SetName("myCustomBucket")
bucket := db.GridFSBucket(bucketOpts)

次のいずれかの方法を使用して、ファイルを GridFS バケットにアップロードできます。

  • UploadFromStream() は、入力ストリームから読み取りを行います

  • OpenUploadStream() は出力ストリームに書込みます

どちらのアップロード プロセスでも、UploadOptionsインスタンス を作成することで構成情報を指定できます。 オプションの完全なリストを表示するには、 loadOptions APIドキュメント を参照してください。

入力ストリームを含むファイルをアップロードするには、 UploadFromStream()メソッドを使用して次のパラメータを含めます。

  • ファイル名

  • io.Readerインスタンス(開いたファイルをパラメータとして含む)

  • optsの動作を変更するための パラメーターUploadFromStream()

次のコード例では、 file.txtというファイルから読み取り、ファイル メタデータを設定するためのoptsパラメータを作成し、その内容を GridFS バケットにアップロードします。

file, err := os.Open("home/documents/file.txt")
uploadOpts := options.GridFSUpload().SetMetadata(bson.D{{"metadata tag", "first"}})
objectID, err := bucket
.UploadFromStream(
"file.txt",
io.Reader(file),
uploadOpts
)
if err != nil {
panic(err)
}
fmt.Printf("New file uploaded with ID %s", objectID)
New file uploaded with ID ...

出力ストリームを使用してファイルをアップロードするには、 OpenUploadStream()メソッドを使用して次のパラメータを含めます。

  • ファイル名

  • optsの動作を変更するための パラメーターOpenUploadStream()

次のコード例では、GridFS バケットでアップロードストリームを開き、オプション パラメーターに各チャンク内のバイト数を設定します。 次に、 file.txtのコンテンツに対してWrite()メソッドを呼び出して、そのコンテンツをストリームに書込みます。

file, err := os.Open("home/documents/file.txt")
if err != nil {
panic(err)
}
// Defines options that specify configuration information for files
// uploaded to the bucket
uploadOpts := options.GridFSUpload().SetChunkSizeBytes(200000)
// Writes a file to an output stream
uploadStream, err := bucket.OpenUploadStream("file.txt", uploadOpts)
if err != nil {
panic(err)
}
fileContent, err := io.ReadAll(file)
if err != nil {
panic(err)
}
var bytes int
if bytes, err = uploadStream.Write(fileContent); err != nil {
panic(err)
}
fmt.Printf("New file uploaded with %d bytes written", bytes)
// Calls the Close() method to write file metadata
if err := uploadStream.Close(); err != nil {
panic(err)
}

GridFS バケットのfilesコレクションに保存されているファイル メタデータを検索できます。 filesコレクション内の各ドキュメントには、次の情報が含まれています。

  • ファイル ID

  • ファイルの長さ

  • 最大チャンク サイズ

  • アップロード日時

  • ファイル名

  • その他の情報を保存する metadataドキュメント

ファイルデータを検索するには、 GridFSBucketインスタンスでFind()メソッドを呼び出します。 特定のファイル ドキュメントのみを一致させるには、クエリフィルターを引数としてFind()に渡すことができます。

注意

クエリフィルターをFind()メソッドに渡す必要があります。 filesコレクション内のすべてのドキュメントを検索するには、空のクエリフィルターをFind()に渡します。

次の例では、 lengthの値が1500より大きいドキュメントのファイル名と長さを検索します。

filter := bson.D{{"length", bson.D{{"$gt", 1500}}}}
cursor, err := bucket.Find(filter)
if err != nil {
panic(err)
}
type gridFSFile struct {
Name string `bson:"filename"`
Length int64 `bson:"length"`
}
var foundFiles []gridFSFile
if err = cursor.All(context.TODO(), &foundFiles); err != nil {
panic(err)
}
for _, file := range foundFiles {
fmt.Printf("filename: %s, length: %d\n", file.Name, file.Length)
}

次のいずれかの方法を使用して、GridFS ファイルをダウンロードできます。

  • DownloadToStream() は、出力ストリームにファイルをダウンロードします

  • OpenDownloadStream()(入力ストリームを開きます)

DownloadToStream()メソッドを使用して、GridFS バケット内のファイルを出力ストリームに直接ダウンロードできます。 DownloadToStream()メソッドは、ファイル ID とio.Writerインスタンスをパラメータとして受け取ります。 このメソッドは、指定されたファイル ID を持つファイルをダウンロードし、 io.Writerインスタンスに書込みます。

次の例では、 ファイルをダウンロードし、ファイル バッファに書込みます。

id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88")
fileBuffer := bytes.NewBuffer(nil)
if _, err := bucket.DownloadToStream(id, fileBuffer); err != nil {
panic(err)
}

OpenDownloadStream()メソッドを使用して、入力ストリームを使用して GridFS バケット内のファイルをメモリにダウンロードできます。 OpenDownloadStream()メソッドは、ファイル ID をパラメーターとして受け取り、ファイルを読み取ることができる入力ストリームを返します。

次の例では、ファイルをメモリにダウンロードし、その内容を読み取ります。

id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88")
downloadStream, err := bucket.OpenDownloadStream(id)
if err != nil {
panic(err)
}
fileBytes := make([]byte, 1024)
if _, err := downloadStream.Read(fileBytes); err != nil {
panic(err)
}

バケット内の GridFS ファイルの名前を更新するには、 Rename()メソッドを使用します。 ファイル ID 値と新しいfilename値を引数としてRename()に渡します。

次の例では、ファイルの名前を"mongodbTutorial.zip"に変更します。

id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88")
if err := bucket.Rename(id, "mongodbTutorial.zip"); err != nil {
panic(err)
}

GridFS バケットからファイルを削除するには、 Delete()メソッドを使用します。 ファイル ID の値を引数としてDelete()に渡します。

次の例では、 ファイルを削除しています。

id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88")
if err := bucket.Delete(id); err != nil {
panic(err)
}

GridFS バケットは、 Drop()メソッドを使用して削除できます。

次のコード例では、GridFS バケットを削除します。

if err := bucket.Drop(); err != nil {
panic(err)
}

GridFS とストレージの詳細については、サーバー マニュアルの次のページを参照してください。

このガイドで言及されているメソッドとタイプの詳細については、次のAPIドキュメントを参照してください。