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

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

图片转代码服务由CSDN问答提供 功能建议

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

因此,在重构了此任务中包含的大多数服务之后,我注意到新的正式mongo驱动程序不会执行此操作?

所以我决定尝试手动添加此字段,但是到了我无法理解的程度?

尝试了< code> options.GridFSUpload()。SetMetadata(metadata),但我不了解它的逻辑,互联网对于新的mongo驱动程序在GO中的运行来说确实很小。

任何人都可以给我提示如何将自定义字段添加到文件文档中吗? ntType !!

真的很感激。

这是我尝试做的一个例子

   // GridFSInsert-
func GridFSInsert(文件名字符串,数据[] byte,元数据... bsonx.Elem)(primitive.ObjectID,错误){
 checkMongoConnection(false)
 var fileID original.ObjectID 
  bucket,bucketErr:= gridFs.NewBucket(
 Mongo.Client.Database(Mongo.DBName),
 options.GridFSBucket()。SetName(gridFSColName),
)
 if bucketErr!= nil {
返回fileID  ,bucketErr 
} 
 uploadStream,uploadStreamErr:= bucket.OpenUploadStream(
 fileName,
 options.GridFSUpload()。SetMetadata(metadata),
)
 if uploadStreamErr!= nil {
返回fileID,uploadStreamErr  
} 
延迟uploadStream.Close()
 
 fileSize,writeErr:= uploadStream.Write(data)
 if writeErr!= nil {
返回fileID,writeErr 
} 
 fileID = uploadStream.FileID  
 log.Printf(“将文件成功写入数据库,文件大小:%d”,fileS  ize)
 
返回文件ID,nil 
} 
   
 
 

对不起,如果我错过了一些事情,因为我对GO的了解不如我想的那样。

感谢您的帮助

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

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.

    打赏 评论
  • dtc9222 2019-02-15 21:37

    Here is an example of 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)
    }
    

    Here is the full example

    打赏 评论

相关推荐 更多相似问题