Om de "Mijn echte vraag:hoe kan ik het gedrag van mgo vóór upsert aan te passen? " - u kunt bson marshalling aanpassen door bson Getter te definiëren naar het model.
Laten we, om te illustreren hoe het werkt, het model vereenvoudigen om geneste documenten te voorkomen:
type Game struct {
ID int `bson:"_id"`
Name string
Stats [] float64
}
Met newGame als volgt:
newGame := Game{
ID: 1,
Name: "foo",
Stats: []{5.0}
}
De update col.UpsertId(newGame.ID, newGame)
standaard marshals newGame
in JSON, waarbij mongo-query's worden geproduceerd zoals:
update({_id:1}, {name: "foo", stats: [5]}, {upsert: true});
Om gebruik te maken van $set
, $push
enz., kunt u een aangepaste bson-getter definiëren. Bijv.
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
}
Dus de update col.UpsertId(newGame.ID, newGame)
zal een mongodb-query produceren
update({_id:1}, {$set: {name: "foo"}, $push: {stats: {$each: [5]}}}, {upsert: true});
Om het glashelder te maken:de aangepaste marshaler zal worden gebruikt in alle mgo-query's, dus u wilt deze waarschijnlijk niet rechtstreeks naar het model definiëren, maar naar de afgeleide ervan om alleen in upsert-bewerkingen te gebruiken:
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})