大家好,我们又见面了啊~本文《MonGo-go-driver GridFS 元数据》的内容中将会涉及到等等。如果你正在学习golang相关知识,欢迎关注我,以后会给大家带来更多Golang相关文章,希望我们能一起进步!下面就开始本文的正式内容~
问题内容
我为我工作的公司编写了一个聊天应用程序,并且我与 mgo 驱动程序一起工作了一段时间。 现在我们将 mgo 重构为官方 mongo 驱动程序。 我已经实现了 gridfs 来处理聊天文件,因为它们并不大,而且它简化了工作。 以前的 mgo 驱动程序在保存文件时有一个数据列表,其中一个字段是 contenttype(很好,对吧?)
因此,在重构此任务中包含的大部分服务后,我注意到新的官方 mongo 驱动程序不会执行此操作?
所以我决定尝试手动添加此字段,但后来我发现我不明白该怎么做?
尝试过 options.gridfsupload().setmetadata(metadata) 但我不明白它的逻辑,而且互联网对于在 go 中工作的新 mongo 驱动程序的结果来说确实很小。
任何人都可以给我提示如何将自定义字段添加到文件文档吗? 喜欢内容类型!!
非常感谢。
这是我尝试做的一个例子
// 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”字段。
这有点道理。驱动程序从字面上遵循规范的措辞 - 除了 metadata 之外,无法在任何地方创建 contenttype 属性,但 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)
}
这是 full example
今天关于《Mongo-go-driver GridFS 元数据》的内容介绍就到此结束.