Aby odpowiedzieć na „Moje prawdziwe pytanie:jak mogę dostosować zachowanie mgo przed upsert? „ – możesz dostosować marshalling bson, definiując bson Getter do modelu.
Aby zilustrować, jak to działa, uprośćmy model, aby uniknąć zagnieżdżonych dokumentów:
type Game struct {
ID int `bson:"_id"`
Name string
Stats [] float64
}
W nowej grze w następujący sposób:
newGame := Game{
ID: 1,
Name: "foo",
Stats: []{5.0}
}
Aktualizacja col.UpsertId(newGame.ID, newGame)
domyślnie marszałkowie newGame
w JSON, tworząc zapytanie mongo takie jak:
update({_id:1}, {name: "foo", stats: [5]}, {upsert: true});
Aby skorzystać z $set
, $push
itp., możesz zdefiniować niestandardowy getter bson. Np.
func (g Game) GetBSON() (interface{}, error) {
return bson.M{
"$set": bson.M{"name": g.Name},
"$push": bson.M{"stats": bson.M{"$each": g.Stats}},
}, nil
}
Tak więc aktualizacja col.UpsertId(newGame.ID, newGame)
wygeneruje zapytanie mongodb
update({_id:1}, {$set: {name: "foo"}, $push: {stats: {$each: [5]}}}, {upsert: true});
Aby wszystko było jasne - niestandardowy marshaler będzie używany we wszystkich zapytaniach mgo, więc prawdopodobnie nie chcesz definiować go bezpośrednio do modelu, ale do jego pochodnej do użycia tylko w operacjach upsert:
type UpdatedGame struct {
Game
}
func (g UpdatedGame) GetBSON() (interface{}, error) {
return bson.M{....}
}
.....
newGame := Game{
ID: 1,
Name: "foo",
Stats: []{5.0}
}
col.UpsertId(newGame.ID, UpdatedGame{newGame})