douquanqiao6788 2019-02-15 15:54 采纳率: 100%
浏览 288
已采纳

Mongo-go-Driver GridFS元数据

I have written a chat app for the company I work in and I worked with the mgo driver for some time. Now we refactor the mgo to the official mongo driver. I have implemented GridFS to work with the chat files as they are not big and it simplifies the job. The previous mgo driver when saving files had a list of data which one of the fields was contentType (Great right?)

So after refactoring most of the services that were included in this task I have noticed that the new official mongo driver does not do this??

So I have decided to try and add this field manually but then I got to the point that I don't understand how I can?

Tried with options.GridFSUpload().SetMetadata(metadata) but I don't understand the logic of it and the internet is really minimal with the result about the new mongo driver working in GO.

Anyone can give me a hint how to add custom fields to file docs? Like contentType!!

Really appreciate it.

This is an example of what I tried to do

// 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
}

Sorry if I missed something as I'm not that experienced with GO as I would like to.

Thanks for any help

  • 写回答

2条回答 默认 最新

  • doujianglin6704 2019-02-16 22:33
    关注

    There is no logic you are trying to understand. The reason why you can't find much about contentType in new official mongo driver is because contentType has been deprecated in gridfs spec long before the driver was written.

    I must admit the gridfs documentation doesn't mention it. In fact official mongofiles cli still uses legacy format.

    The spec puts it straight:

    Note: some older versions of GridFS implementations allowed applications to add arbitrary fields to the files collection document at the root level. New implementations of GridFS will not allow this, but must be prepared to handle existing files collection documents that might have additional fields.

    And if you like more detailed official reasoning :

    Why is contentType deprecated?

    Most fields in the files collection document are directly used by the driver, with the exception of: metadata, contentType and aliases. All information that is purely for use of the application should be embedded in the 'metadata' document. Users of GridFS who would like to store a contentType for use in their applications are encouraged to add a 'contentType' field to the ‘metadata’ document instead of using the deprecated top-level ‘contentType’ field.

    Which kinda makes sense. The driver follows wording of the spec literally - there is no way to create contentType property anywhere but in metadata, yet Bucket.Find will still return contentType of files created by "older versions".

    The one-off transition from legacy gridfs to new format can be as simple as:

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

    Assuming your bucket is default "fs" and you are not going to upload files in legacy format. If you have a luxury of free space, it won't be a terrible idea to out to new temporary collection, validate it, then rename.

    If you have to support legacy format for any reason, you still can access gridfs collections directly:

    // 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}}}},
    )
    

    Where "fs" is your bucket name, and contentType is the string value you want to set as a contentType.

    Bear in mind, that "some older versions" use int32 for file length tho. The new driver expects it to be int64. It should be okay for Find-like operations that work with *.fiiles collections alone but may cause problems downloading such files with new official driver.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥50 导入文件到网吧的电脑并且在重启之后不会被恢复
  • ¥15 (希望可以解决问题)ma和mb文件无法正常打开,打开后是空白,但是有正常内存占用,但可以在打开Maya应用程序后打开场景ma和mb格式。
  • ¥20 ML307A在使用AT命令连接EMQX平台的MQTT时被拒绝
  • ¥20 腾讯企业邮箱邮件可以恢复么
  • ¥15 有人知道怎么将自己的迁移策略布到edgecloudsim上使用吗?
  • ¥15 错误 LNK2001 无法解析的外部符号
  • ¥50 安装pyaudiokits失败
  • ¥15 计组这些题应该咋做呀
  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能