当前位置: 首页 > 面试题库 >

mongodb-go-driver / bson结构转换为bson.Document编码

周朗
2023-03-14
问题内容

我正在使用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(...)或手动编码每个非空字段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文档构建器是否可以实现相同的目的?

UPD。我的问题的全部内容:我编写了REST端点,用于 部分 更新“注释”文档(存储在MongoDB中)。我现在拥有的代码:

var noteUpdate models.NoteUpdate
ctx.BindJSON(&noteUpdate)    
//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(&noteUpdate)    
//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", &noteUpdate)),
        ),
    findopt.OptReturnDocument(option.After),
)

代码,我 希望有

var noteUpdate models.NoteUpdate
ctx.BindJSON(&noteUpdate)
//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标签动态构建* bson.Document (没有像我的SetWrapper这样的预定义包装器)?


问题答案:

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

您可以创建一个辅助函数,将其“转换”为一个bson.Document类似这样的结构值:

func toDoc(v interface{}) (doc *bson.Document, 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()将来会有所改进,并允许直接传递结构值或指向结构值的指针。



 类似资料:
  • 问题内容: 我是mongodb-go-driver的新手。但是我被困住了。 查看m [id]的内容时,它没有内容-全部为null。 我的地图是这样的:m map [string] Language 语言定义如下: 我究竟做错了什么? 我正在使用此示例进行学习:https : //github.com/mongodb/mongo-go- driver/blob/master/examples/doc

  • 问题内容: 我想将mongo-go-driver中的 bson转换为json。 我应该小心处理,因为如果数据中存在则失败。 例如,我想将以下bson数据转换为json。 以下失败。 问题答案: 如果您知道BSON的结构,则可以创建一个实现和接口的自定义类型,并根据需要处理NaN。例: 如果您的BSON具有任意结构,则唯一的选择是使用反射遍历该结构,并将所有出现的NaN转换为类型(可能是如上所述的自

  • 问题内容: 在将结果转换为JSON之前,我不想使用结构。假设我有一些结果: 我可以在 docs 变量中收集所有结果,并在 doc 变量中收集最后一个结果: 我可以轻松地将最后的结果转换为JSON,而无需使用任何结构: 我无法将文档转换为JSON,因此无法在我的Rest服务器中使用。 更新2019-01-17: 我在我的REST服务器中使用result像这样: 因此它不可能是遍历值的循环。问题:如何

  • 问题内容: 我正在尝试使用该包将Go结构转换为JSON,但我得到的只是。我敢肯定这是完全显而易见的,但我看不到。 然后,当我尝试运行它时,我得到以下信息: 问题答案: 您需要导出的字段,以便在包装可以看到它。将字段重命名为。 输出:

  • 问题内容: 我有一些代码可以从集合中提取所有文档并将其放到网页上。简化版本如下所示: 我有一个driveInfo集合,其中包含很长的文档列表。每个文档包含嵌套的对象。我想做的是,每当有人在其浏览器中访问/ drive时,将整个集合打印为json对象,以便以后可以用jquery抓取所有内容(api的开头) 但是,我收到一条错误消息:“ TypeError:将圆形结构转换为JSON”。页面上的错误指向

  • 问题内容: 我正在尝试将可工作的mongo查询转换为golang中的bson。我掌握了一些基本知识,但仍在努力寻找如何将更高级的查询集成到组合中的方法。 有人可以帮助我转换以下查询吗?希望它应该给我我需要的方向…不幸的是,除了评估和查询之外,我无法找到许多示例。 这在mongo中有效: 这适用于golang / bson: 我该如何正确介绍该声明? 问题答案: 在您的情况下,它将是: