Mongo-go-Driver GridFS元数据

时间:2019-02-15 15:54:26

标签: mongodb go gridfs

我已经为所工作的公司编写了一个聊天应用程序,并且与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经验。

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

这里是# A tibble: 12 x 4 # Groups: group [4] item group query direction <chr> <dbl> <dbl> <dbl> 1 a 1 0 1 2 b 1 1 1 3 c 1 0 1 4 d 2 0 -1 5 e 2 1 1 6 f 2 0 1 7 i 3 0 -1 8 h 3 1 1 9 g 3 0 -1 10 l 4 0 1 11 k 4 1 1 12 j 4 0 1 的示例。

SetMetadata()

这里是docs

答案 1 :(得分: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作为文件长度tho。新的驱动程序希望它是int64。 对于仅适用于* .fiiles集合的类似Find的操作应该可以,但可能会导致使用新的官方驱动程序下载此类文件时出现问题。