MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Personalize a operação de upsert do mgo


Para responder a "Minha pergunta real:Como posso personalizar o comportamento do mgo antes do upsert? " - você pode personalizar o marshalling bson definindo bson Getter ao modelo.

Para ilustrar como funciona, vamos simplificar o modelo para evitar documentos aninhados:
type Game struct {
    ID int `bson:"_id"`
    Name string
    Stats [] float64
}

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

A atualização col.UpsertId(newGame.ID, newGame) por padrão, os marechais newGame em JSON, produzindo consulta mongo como:
update({_id:1}, {name: "foo", stats: [5]}, {upsert: true});

Para usar $set , $push etc, você pode definir um getter bson personalizado. Por exemplo.
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
}

Portanto, a atualização col.UpsertId(newGame.ID, newGame) irá produzir uma consulta mongodb
update({_id:1}, {$set: {name: "foo"}, $push: {stats: {$each: [5]}}}, {upsert: true});

Para deixar bem claro - o empacotador personalizado será usado em todas as consultas mgo, então você provavelmente não deseja defini-lo diretamente no modelo, mas em seu derivado para usar apenas em operações de 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})