Mongo-go-driver GridFS元数据

问题描述 投票:0回答:2

我为我工作的公司写了一个聊天应用程序,我和mgo驱动程序一起工作了一段时间。现在我们将mgo重构为官方mongo驱动程序。我已经实现了GridFS来处理聊天文件,因为它们并不大,它简化了工作。保存文件时的前一个mgo驱动程序有一个数据列表,其中一个字段是contentType(很棒?)

所以在重构了这个任务中包含的大多数服务后,我注意到新的官方mongo驱动程序没有这样做?

所以我决定尝试手动添加这个字段,但后来我发现我不明白我怎么做?

尝试与options.GridFSUpload().SetMetadata(metadata),但我不明白它的逻辑和互联网真的很小与新的mongo驱动程序在GO工作的结果。

任何人都可以给我一个提示如何将自定义字段添加到文件文档?喜欢contentType !!

真的很感激。

这是我试图做的一个例子

// GridFSInsert -
func GridFSInsert(fileName string, data []byte, metadata ...bsonx.Elem) (primitive.ObjectID, error) {
    checkMongoConnection(false)
    var fileID primitive.ObjectID
    bucket, bucketErr := gridFs.NewBucket(
        Mongo.Client.Database(Mongo.DBName),
        options.GridFSBucket().SetName(gridFSColName),
    )
    if bucketErr != nil {
        return fileID, bucketErr
    }
    uploadStream, uploadStreamErr := bucket.OpenUploadStream(
        fileName,
        options.GridFSUpload().SetMetadata(metadata),
    )
    if uploadStreamErr != nil {
        return fileID, uploadStreamErr
    }
    defer uploadStream.Close()

    fileSize, writeErr := uploadStream.Write(data)
    if writeErr != nil {
        return fileID, writeErr
    }
    fileID = uploadStream.FileID
    log.Printf("Write file to DB was succesful, File size: %d", fileSize)

    return fileID, nil
}

对不起,如果我错过了一些东西,因为我不是那种经验丰富的GO,因为我想。

谢谢你的帮助

mongodb go gridfs
2个回答
1
投票

没有你想要理解的逻辑。你在新的官方mongo驱动程序中找不到很多关于contentType的原因是因为contentType has been deprecated in gridfs spec早在驱动程序编写之前。

我必须承认gridfs documentation没有提到它。事实上,官方mongofiles cli仍然使用传统格式。

规范直截了当:

注意:一些较旧版本的GridFS实现允许应用程序在根级别向文件集合文档添加任意字段。 GridFS的新实现不允许这样做,但必须准备好处理可能包含其他字段的现有文件集合文档。

如果你想更详细的official reasoning

为什么不赞成使用contentType?

文件集合文档中的大多数字段都由驱动程序直接使用,但元数据,contentType和别名除外。纯粹用于应用程序的所有信息都应嵌入“元数据”文档中。希望存储要在其应用程序中使用的contentType的GridFS用户将“contentType”字段添加到“元数据”文档,而不是使用已弃用的顶级“contentType”字段。

哪种有道理。驱动程序遵循规范的字面意思 - 没有办法在contentType中创建metadata属性,但Bucket.Find仍将返回由“旧版本”创建的文件的contentType

从传统gridfs到新格式的一次性转换可以简单到:

db.getCollection("fs.files").aggregate([
    {$addFields: { 
        "length" : {$toLong: "$length"},
        "metadata.contentType": { $ifNull: [ "$contentType", "$metadata.contentType" ] } 
    }},
    { $out : "fs.files" }
])

假设您的存储桶是默认的“fs”,并且您不打算以传统格式上传文件。如果你有一个奢侈的自由空间,out到新的临时收藏,验证它,然后重命名将不是一个可怕的想法。

如果您出于任何原因必须支持旧格式,您仍然可以直接访问gridfs集合:

// in your code snippet after
fileID = uploadStream.FileID

// update the document that represent uploaded file
files := db.Collection("fs.files")
updateResult, err := files.UpdateOne(
    context.Background(),
    bson.D{{"_id", fileID}},
    bson.D{{"$set", bson.D{{"contentType", contentType}}}},
)

其中“fs”是您的存储桶名称,而contentType是您要设置为contentType的字符串值。

请记住,“一些旧版本”使用int32作为文件长度。新驱动程序希望它是int64。对于仅使用* .fiiles集合的类似Find的操作应该没问题,但是可能会导致使用新的官方驱动程序下载这些文件时出现问题。


1
投票

这是SetMetadata()的一个例子。

opts := options.GridFSUpload()
opts.SetMetadata(bsonx.Doc{{Key: "content-type", Value: bsonx.String("application/json")}})
if ustream, err = bucket.OpenUploadStream("test.txt", opts); err != nil {
    t.Fatal(err)
}

这是full example

© www.soinside.com 2019 - 2024. All rights reserved.