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

Golang官方MongoDB驱动ObjectID怪异行为

Golang官方MongoDB驱动ObjectID怪异行为

Go
慕容708150 2022-05-18 09:32:40
我正在尝试在 golang 中使用官方的 mongodb 驱动程序,但看到了一些意想不到的东西。如果我有一个像type User struct {    ID     primitive.ObjectID `json:"id" bson:"_id"`    Name   string             `json:"name" bson:"name"`    Email  string             `json:"email" bson:"email"`}我用它创建了一个新实例,Name但Email省略了 ID,期望数据库将用它的值填充它。相反,它使用全零,因此第二个等插入失败multiple write errors: [{write errors: [{E11000 duplicate key error collection: collection.name index: _id_ dup key: { : ObjectId('000000000000000000000000') }}]}, {<nil>}]如果我使用 a*primitive.ObjectID我只会得到相同类别的错误null而不是零multiple write errors: [{write errors: [{E11000 duplicate key error collection: collection.name index: _id_ dup key: { : null }}]}, {<nil>}]我是否使用omitempty指令都没关系,相同的结果。如果我完全省略该ID字段,它可以工作,但是我的结构上没有该数据。有没有办法让数据库处理 ID?或者我必须明确调用NewObjectID()结构上的函数吗?
查看完整描述

2 回答

?
翻翻过去那场雪

TA贡献2065条经验 获得超14个赞

我是否使用 omitempty 指令都没关系,结果相同。


omitempty标记ID应该可以工作。例如:


type User struct {

    ID     primitive.ObjectID `json:"id" bson:"_id,omitempty"`

    Name   string             `json:"name" bson:"name"`

    Email  string             `json:"email" bson:"email"`

}


collection.InsertOne(context.Background(), User{Name:"Foo", Email:"Baz"})

如果您不指定omitepmty标记,那么您观察到的行为只是Go 结构行为;因此,如果省略任何结构字段,它将为零值。在这种情况下,因为您已将字段类型指定为original.ObjectID,ObjectId('000000000000000000000000')所以是零值。


这就是为什么您需要在插入之前先生成一个值的原因,即:


collection.InsertOne(context.Background(), 

                     User{ ID: primitive.NewObjectID(), 

                           Name: "Foo", 

                           Email: "Bar"})

有没有办法让数据库处理 ID?


从技术上讲,如果在发送到服务器之前未提供ObjectId,MongoDB 驱动程序会自动生成它。


您可以尝试在插入时使用bson.M而不是 struct 以省略该_id字段,即


collection.InsertOne(context.Background(), 

                     bson.M{"name":"Foo", "email":"Bar"})

上面的代码片段是使用mongo-go-driver v1.3.x 编写的


查看完整回答
反对 回复 2022-05-18
?
慕的地6264312

TA贡献1817条经验 获得超6个赞

omitemptystruct 标签应该可以工作:


type User struct {

    ID     primitive.ObjectID `json:"id" bson:"_id,omitempty"`

    Name   string             `json:"name" bson:"name"`

    Email  string             `json:"email" bson:"email"`

}

该primitive.ObjectID类型实现了bsoncodec.Zeroer接口,因此如果它是空对象 ID(全为 0),则应从文档中省略它,并且驱动程序将为您生成一个新的。你可以试试这个并发布输出吗?


查看完整回答
反对 回复 2022-05-18
  • 2 回答
  • 0 关注
  • 141 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号