mongodb-go-driver/bson结构转换为bson.Document编码 [英] mongodb-go-driver/bson struct to bson.Document encoding
问题描述
我正在使用 https://github.com/mongodb/mongo-go-driver 和 当前正在尝试对该结构进行部分更新
I'm working with https://github.com/mongodb/mongo-go-driver and currently trying to implement a partial update of such struct
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" }
然后,我希望存储文档中唯一的标题"字段将被更改.
Then I expect that the only "title" field in the stored document will be changed.
我需要写一些类似的东西
I need to write something like
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(...)
或bson.EC.Int64(...)
手动编码每个非空字段.我尝试使用bson.EC.InterfaceErr(...)
但出现错误
The problem is that I don't want to manually encode each non-empty field with bson.EC.String(...)
or bson.EC.Int64(...)
. I tried to use bson.EC.InterfaceErr(...)
but got an error
无法为* models.NoteUpdate类型创建元素,请尝试使用bsoncodec.ConstructElementErr
Cannot create element for type *models.NoteUpdate, try using bsoncodec.ConstructElementErr
不幸的是,bsoncodec中没有这样的功能.我发现的唯一方法是创建包装器
Unfortunately, there is no such function in bsoncodec. The only way I found is to create wrapper
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文档构建器实现相同的功能吗?
It works, but is it possible to achieve the same with bson/bsoncodec document builders ?
UPD.我的问题的全部内容: 我编写了REST端点,用于部分更新"Note"文档(存储在MongoDB中).我现在拥有的代码:
UPD. The full context of my question: I wrote the REST endpoint for partially updating "Note" documents(stored in MongoDB). Code that I have now:
var noteUpdate models.NoteUpdate
ctx.BindJSON(¬eUpdate)
//omit validation and errors handling
updateParams := services.SetWrapper{Set: noteUpdate}
res := collection.FindOneAndUpdate(
context.Background(),
bson.NewDocument(bson.EC.String("_id", noteUpdate.ID)),
updateParams,
findopt.OptReturnDocument(option.After),
)
我想要的代码
var noteUpdate models.NoteUpdate
ctx.BindJSON(¬eUpdate)
//omit validation and errors handling
res := collection.FindOneAndUpdate(
context.Background(),
bson.NewDocument(bson.EC.String("_id", noteUpdate.ID)),
bson.NewDocument(
//bsoncodec.ConstructElement doesn't exists
bsoncodec.ConstructElement("$set", ¬eUpdate)),
),
findopt.OptReturnDocument(option.After),
)
我不想想要的代码
var noteUpdate models.NoteUpdate
ctx.BindJSON(¬eUpdate)
//omit validation and errors handling
bsonNote := bson.NewDocument()
if noteUpdate.Title != "" {
bsonNote.Append(bson.EC.String("title", noteUpdate.Title))
}
if noteUpdate.Content != "" {
bsonNote.Append(bson.EC.String("content", noteUpdate.Content))
}
//..setting the rest of the fields...
res := collection.FindOneAndUpdate(
context.Background(),
bson.NewDocument(bson.EC.String("_id", noteUpdate.ID)),
bson.NewDocument(bson.EC.SubDocument("$set", bsonNote)),
findopt.OptReturnDocument(option.After),
)
因此,确切的问题是-是否有任何方法可以基于bson
标签(没有像我的SetWrapper这样的预定义包装器)动态地构建* bson.Document?
So, the precise question is - is there any way to build *bson.Document dynamically based on bson
tags(without predefined wrappers like my SetWrapper)?
推荐答案
很遗憾,当前不支持此功能.
Unfortunately this is currently not supported.
You may create a helper function which "converts" a struct value to a bson.Document
like this:
func toDoc(v interface{}) (doc *bson.Document, err error) {
data, err := bson.Marshal(v)
if err != nil {
return
}
err = bson.Unmarshal(data, &doc)
return
}
然后可以像这样使用它:
Then it can be used like this:
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()
将将来会有所改进,并允许直接将结构值或指针传递给结构值.
Hopefully ElementConstructor.Interface()
will improve in the future and allow passing struct values or pointers to struct values directly.
这篇关于mongodb-go-driver/bson结构转换为bson.Document编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!