For at besvare "Mit rigtige spørgsmål:Hvordan kan jeg tilpasse adfærden af mgo før upsert? " - du kan tilpasse bson marshalling ved at definere bson Getter til modellen.
For at illustrere, hvordan det virker, lad os forenkle modellen for at undgå indlejrede dokumenter:
type Game struct {
ID int `bson:"_id"`
Name string
Stats [] float64
}
Med newGame som følger:
newGame := Game{
ID: 1,
Name: "foo",
Stats: []{5.0}
}
Opdateringen col.UpsertId(newGame.ID, newGame)
som standard marshals newGame
ind i JSON, producerer mongo-forespørgsler som:
update({_id:1}, {name: "foo", stats: [5]}, {upsert: true});
For at gøre brug af $set
, $push
osv., kan du definere en brugerdefineret bson getter. F.eks.
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
}
Så opdateringen col.UpsertId(newGame.ID, newGame)
vil producere en mongodb-forespørgsel
update({_id:1}, {$set: {name: "foo"}, $push: {stats: {$each: [5]}}}, {upsert: true});
For at gøre det krystalklart - den brugerdefinerede marshaler vil blive brugt i alle mgo-forespørgsler, så du vil sandsynligvis ikke definere den direkte til modellen, men til dens afledte til kun at bruge i upsert-operationer:
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})