MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Personnaliser l'opération upsert mgo

Pour répondre à la "Ma vraie question :comment puis-je personnaliser le comportement de mgo avant l'upsert ? " - vous pouvez personnaliser le marshalling bson en définissant bson Getter au modèle.

Pour illustrer son fonctionnement, simplifions le modèle pour éviter les documents imbriqués :

type Game struct {
    ID int `bson:"_id"`
    Name string
    Stats [] float64
}

Avec newGame comme suit :

newGame := Game{
    ID: 1,
    Name: "foo",
    Stats: []{5.0}
}

La mise à jour col.UpsertId(newGame.ID, newGame) par défaut marshals newGame en JSON, produisant une requête mongo comme :

update({_id:1}, {name: "foo", stats: [5]}, {upsert: true});

Pour utiliser $set , $push etc, vous pouvez définir un getter bson personnalisé. Par exemple

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
}

Donc la mise à jour col.UpsertId(newGame.ID, newGame) produira une requête mongodb

update({_id:1}, {$set: {name: "foo"}, $push: {stats: {$each: [5]}}}, {upsert: true});

Pour le rendre parfaitement clair - le marshaleur personnalisé sera utilisé dans toutes les requêtes mgo, vous ne voudrez donc probablement pas le définir directement sur le modèle, mais sur son dérivé à utiliser uniquement dans les opérations d'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})