为了账号安全,请及时绑定邮箱和手机立即绑定

mongodb-go-driver/bson struct 到 bson.Document 编码

mongodb-go-driver/bson struct 到 bson.Document 编码

Go
撒科打诨 2023-05-04 17:43:51
我正在使用https://github.com/mongodb/mongo-go-driver,目前正在尝试实现此类结构的部分更新type NoteUpdate struct {    ID        string `json:"id,omitempty" bson:"_id,omitempty"`    Title     string `json:"title" bson:"title,omitempty"`    Content   string `json:"content" bson:"content,omitempty"`    ChangedAt int64  `json:"changed_at" bson:"changed_at"`}例如,如果我有noteUpdate := NoteUpdate{ Title: "New Title" }然后我希望存储文档中唯一的“标题”字段将被更改。我需要写类似的东西collection.FindOneAndUpdate(context.Background(),    bson.NewDocument(bson.EC.String("_id", noteUpdate.ID)),    // I need to encode non-empty fields here    bson.NewDocument(bson.EC.SubDocument("$set", bson.NewDocument(...))))问题是我不想用bson.EC.String(...)or手动编码每个非空字段bson.EC.Int64(...)。我尝试使用bson.EC.InterfaceErr(...)但出现错误无法为 *models.NoteUpdate 类型创建元素,请尝试使用 bsoncodec.ConstructElementErr不幸的是,bsoncodec 中没有这样的功能。我发现的唯一方法是创建包装器type SetWrapper struct {    Set interface{} `bson:"$set,omitempty"`}并像使用它partialUpdate := &NoteUpdate{    ID: "some-note-id",     Title: "Some new title", }updateParam := SetWrapper{Set: partialUpdate}collection.FindOneAndUpdate(    context.Background(),    bson.NewDocument(bson.EC.String("_id", noteUpdate.ID)),    updateParam,)它有效,但是否可以使用 bson/bsoncodec 文档构建器实现相同的效果?更新。我的问题的完整上下文:我编写了用于部分更新“注释”文档(存储在 MongoDB 中)的 REST 端点。我现在拥有的代码:var noteUpdate models.NoteUpdatectx.BindJSON(&noteUpdate)    //omit validation and errors handlingupdateParams := services.SetWrapper{Set: noteUpdate}res := collection.FindOneAndUpdate(context.Background(),bson.NewDocument(bson.EC.String("_id", noteUpdate.ID)),    updateParams,    findopt.OptReturnDocument(option.After),)所以,确切的问题是——有没有什么方法可以基于bson标签动态构建 *bson.Document(没有像我的 SetWrapper 这样的预定义包装器)?
查看完整描述

1 回答

?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

不幸的是,目前不支持此功能。


您可以创建一个辅助函数,将结构值“转换”为bson.D如下所示:


func toDoc(v interface{}) (doc *bson.D, err error) {

    data, err := bson.Marshal(v)

    if err != nil {

        return

    }


    err = bson.Unmarshal(data, &doc)

    return

}

然后它可以像这样使用:


partialUpdate := &NoteUpdate{

    Title: "Some new title",

}


doc, err := toDoc(partialUpdate)

// check error


res := c.FindOneAndUpdate(

    context.Background(),

    bson.NewDocument(bson.EC.String("_id", "some-note-id")),

    bson.NewDocument(bson.EC.SubDocument("$set", doc)),

)

希望ElementConstructor.Interface()将来会改进并允许直接传递结构值或指向结构值的指针。



查看完整回答
反对 回复 2023-05-04
  • 1 回答
  • 0 关注
  • 85 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信