我为我工作的公司写了一个聊天应用程序,我和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,因为我想。
谢谢你的帮助
没有你想要理解的逻辑。你在新的官方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的操作应该没问题,但是可能会导致使用新的官方驱动程序下载这些文件时出现问题。
这是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)
}