【问题标题】:How use update function of mongo-go-driver using struct如何使用 struct 使用 mongo-go-driver 的更新功能
【发布时间】:2019-09-18 03:45:01
【问题描述】:

mongo-go-driver的更新函数可以这样调用。

filter := bson.D{"username", username}
update := bson.D{{"$set",
    bson.D{
        {"name", person.Name},
    },
}}
result, err := collection.UpdateOne(ctx, filter, update)
type Person struct {
    ID       primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
    Username string             `json:"username,omitempty" bson:"username,omitempty"`
    Name     string             `json:"name,omitempty" bson:"name,omitempty"`
}

但是,我需要使用 person 结构调用更新函数,而不是像这样提及 person 结构的每个字段。

filter := bson.D{"username", username}
update := bson.D{{"$set", <<how to convert person struct to bson document?>>}}
result, err := collection.UpdateOne(ctx, filter, update)

如何将 person 结构转换为 bson 文档?

【问题讨论】:

  • 你能在哪里解决这个问题?

标签: mongodb go driver crud


【解决方案1】:

将 person 结构编组到 bson 怎么样?

package main

import (
        "fmt"

        "labix.org/v2/mgo/bson"
)

type person struct {
        ID       string `json:"_id,omitempty" bson:"_id,omitempty"`
        Username string `json:"username,omitempty" bson:"username,omitempty"`
        Name     string `json:"name,omitempty" bson:"name,omitempty"`
}

func main() {
        p := person{
                ID:       "id",
                Username: "uname",
                Name:     "name",
        }
        var (
                bm  []byte
                err error
        )
        if bm, err = bson.Marshal(p); err != nil {
                panic(fmt.Errorf("can't marshal:%s", err))
        }
        update := bson.D{{"$set", bm}}
        fmt.Printf("update is:%q\n", update)
}

运行:

 ./sobson
update is:[{"$set" "4\x00\x00\x00\x02_id\x00\x03\x00\x00\x00id\x00\x02username\x00\x06\x00\x00\x00uname\x00\x02name\x00\x05\x00\x00\x00name\x00\x00"}]

【讨论】:

  • 我试过这个方法。但是,我收到了这个错误:多个写入错误:[{写入错误:[{修饰符对字段进行操作,但我们找到了 binData 类型。例如:{$ MOD:{:...}}不{$设置:BinData(0,... 6D0000000275736572000C00000073756D6564686566736673000266697273746E616D65000A00000053756D65647373736400026C6173746E616D65000B0000004469737361)}}]},{}]```跨度>
  • 没有必要将对象编组到 bson - ReplaceOne 应该* 处理它
【解决方案2】:

ReplaceOne 我想这就是你所追求的:

        // Use it's ID to replace
        filter := bson.M{"_id": existing.ID}
        // Create a replacement object using the existing object
        replacementObj := existing
        replacementObj.SomeFieldToChange = "new-replacement-object"
        updateResult, err := coll.ReplaceOne(context.Background(), filter, replacementObj)
        assertNotErr(t, err)
        assertEquals(t, 1, int(updateResult.ModifiedCount))

说明 ErrNotFound 不再像在 mgo 中那样被抛出 - 您必须检查 Modified/Upserted 计数。

【讨论】:

  • 替换和更新有何不同?如果使用替换,是否会重新索引?
  • Replace 用于将整个对象/文档放置到位,而 Update 用于仅更新文档的一部分,例如$inc (increment) 某个整数,$set 一个任意值,等等。这有意义吗?
  • 这是有道理的。你知道它是删除+添加还是修改文档?
  • 有效地就地修改,只需覆盖现有数据并将新数据放入其中。任何存在的内容都会丢失。
【解决方案3】:

你可以这样做:

func Update(person Person) error {
  pByte, err := bson.Marshal(person)
  if err != nil {
    return err
  }

  var update bson.M
  err = bson.Unmarshal(pByte, &update)
  if err != nil {
    return
  }

  // NOTE: filter and ctx(Context) should be already defined
  _, err = collection.UpdateOne(ctx, filter, bson.D{{Key: "$set", Value: update}})
  if err != nil {
    return err
  }
  return nil
}

【讨论】:

  • 我们如何获得“过滤器”对象?请同时添加过滤器代码
  • @MuhammadTariq 我知道它来晚了,但设置过滤器很容易。 filter := bson.D{{"_id", id}} 提问前请先阅读官方文档。 pkg.go.dev/go.mongodb.org/mongo-driver/…
猜你喜欢
  • 2019-03-12
  • 2019-05-21
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 2019-04-06
  • 2023-03-25
相关资源
最近更新 更多