Mongodb 使用mgo强制执行类型映射
当_id成员的类型仅从bson.ObjectId派生时,该成员不再映射到类型ObjectId:Mongodb 使用mgo强制执行类型映射,mongodb,go,bson,mgo,Mongodb,Go,Bson,Mgo,当_id成员的类型仅从bson.ObjectId派生时,该成员不再映射到类型ObjectId: import ( "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) type CustomId bson.ObjectId type Foo struct { ID1 CustomId `bson:"_id"` // broken ID2 bson.ObjectId // mapped as expec
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
type CustomId bson.ObjectId
type Foo struct {
ID1 CustomId `bson:"_id"` // broken
ID2 bson.ObjectId // mapped as expected
}
func main() {
session, _ := mgo.Dial("127.0.0.1")
coll := session.DB("mgodemo").C("foocoll")
doc := Foo{
CustomId(bson.NewObjectId()),
bson.NewObjectId(),
}
coll.Insert(doc)
}
该_id应该是Mongo中的ObjectId。
但结果是字符串被选中了:
Mongo Shell:
这可能是有意的,因为bson.ObjectId本身是从字符串派生的。但在这里,这对我们不利
我们可以告诉mgo将_id映射到数据库中的ObjectId吗?执行此操作时:
type CustomId bson.ObjectId
您正在创建一个新类型,mgo
包将不再看到/识别它为bson.ObjectId
(类型bson.ObjectId
在bson包中是“硬编码的”)。新类型将有0个方法
我会坚持使用bson.ObjectId
。但如果您仍然需要自定义ID类型,则可以在创建CustomId
时使用嵌入:嵌入类型为bson.ObjectId
的值,并使用inline
bson标志作为ID1
字段:
type CustomId struct {
bson.ObjectId `bson:"_id"`
}
type Foo struct {
ID1 CustomId `bson:",inline"`
ID2 bson.ObjectId
}
使用它:
doc := Foo{
CustomId{bson.NewObjectId()},
bson.NewObjectId(),
}
doc := Foo{
bson.NewObjectId(),
bson.NewObjectId(),
}
这样做的好处是CustomId
将拥有bson.ObjectId所拥有的所有方法,您可以添加新方法并“覆盖”现有方法
另一种选择是为您的CustomId
使用接口类型(例如interface{}
),使用它会“简单得多”:
使用它:
doc := Foo{
CustomId{bson.NewObjectId()},
bson.NewObjectId(),
}
doc := Foo{
bson.NewObjectId(),
bson.NewObjectId(),
}
当然,沿着这条路走下去,如果您需要访问CustomId
的包装的bson.ObjectId
,您必须使用和界面来控制mongo中的表示:
type CustomId bson.ObjectId
func (id *CustomId) SetBSON(raw bson.Raw) error {
var v bson.ObjectId
err := raw.Unmarshal(&v)
*id = CustomId(v)
return err
}
func (id CustomId) GetBSON() (interface{}, error) {
return bson.ObjectId(id), nil
}
美好的通过嵌入,我看到了一个缺点,即Foo必须知道CustomId需要内联。仍然很聪明,而且效果很好。