2017-01-11 23 views
2

的_id成員的類型映射未映射到了鍵入的ObjectId,當它的類型僅從bson.ObjectId衍生自:強制與MgO的

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應該已經在蒙戈一個的ObjectId。 但事實證明,是choosen:

蒙戈殼牌:

> db.foocoll.findOne() 
{ "_id" : "XvMn]K� �\f:�", "id2" : ObjectId("58764d6e5d4be120fa0c3ab1") } // id2 is OK ... 

> typeof db.foocoll.findOne()._id 
string // OOps. Should be ObjectId ! 

這可以被預期的,因爲bson.ObjectId本身是從字符串的。但在這裏,這對我們不利。

我們可以告訴mgo將_id映射到數據庫中的ObjectId嗎?

回答

3

使用SetterGetter接口來控制蒙戈表示:

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 
} 
+0

不錯。編輯,以使其可編輯。 – icza

1

當你這樣做:

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(), 
} 

這樣做的優點是CustomId將所有bson.ObjectId有方法,你可以添加新的和「覆蓋」現有的方法。

另一種選擇是使用的接口類型(例如interface{})爲您CustomId,使用它會被很多 「簡單」:

type CustomId interface{} 

type Foo struct { 
    ID1 CustomId  `bson:"_id"` 
    ID2 bson.ObjectId // mapped as expected 
} 

使用它:

doc := Foo{ 
    bson.NewObjectId(), 
    bson.NewObjectId(), 
} 

當然,沿着這條路走,你必須使用type assertion,如果你需要訪問CustomId的包裝bson.ObjectId

+0

與嵌入,我看到的缺點是富必須知道的自訂需要將內聯。仍然聰明,並且運作良好。 – shful