mongodb之Golang官方MongoDB驱动程序ObjectID怪异行为

emanlee 阅读:55 2025-06-02 22:19:02 评论:0

我正在尝试在golang中使用官方的mongodb驱动程序,并且看到了意外情况。

如果我有一个像

type User struct { 
    ID     primitive.ObjectID `json:"id" bson:"_id"` 
    Name   string             `json:"name" bson:"name"` 
    Email  string             `json:"email" bson:"email"` 
} 

我使用 NameEmail创建了一个新的实例,但是省略了ID,期望DB将其值填充其中。相反,它使用全零,因此第二个以此类推的插入失败,并带有
multiple write errors: [{write errors: [{E11000 duplicate key error collection: collection.name index: _id_ dup key: { : ObjectId('000000000000000000000000') }}]}, {<nil>}] 

如果我使用 *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()函数?

请您参考如下方法:

It doesn't matter if I use the omitempty directive or not, same result.


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 structs行为;因此,如果省略任何struct字段,它将为零值。在这种情况下,由于您将字段类型指定为 primitive.ObjectID,因此 ObjectId('000000000000000000000000')为零值。

这就是为什么您需要在插入之前首先生成一个值的原因,即:
collection.InsertOne(context.Background(),  
                     User{ ID: primitive.NewObjectID(),  
                           Name: "Foo",  
                           Email: "Bar"}) 

Is there a way to have the DB handle the ID?



从技术上讲,如果未将 ObjectId发送给服务器,则它是MongoDB驱动程序自动生成的。

您可以在插入时尝试使用 bson.M而不是结构,以忽略 _id字段,即
collection.InsertOne(context.Background(),  
                     bson.M{"name":"Foo", "email":"Bar"}) 

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


标签:mongodb
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号