MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Personalizza l'operazione di upsert mg

Per rispondere alla "La mia vera domanda:come posso personalizzare il comportamento di mgo prima dell'upsert? " - puoi personalizzare il marshalling di bson definendo bson Getter al modello.

Per illustrare come funziona, semplifichiamo il modello per evitare documenti nidificati:

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

Con newGame come segue:

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

L'aggiornamento col.UpsertId(newGame.ID, newGame) per impostazione predefinita esegue il marshalling di newGame in JSON, producendo query mongo come:

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

Per utilizzare $set , $push ecc, puoi definire un getter bson personalizzato. Es.

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
}

Quindi l'aggiornamento col.UpsertId(newGame.ID, newGame) produrrà una query mongodb

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

Per chiarire, il marshaler personalizzato verrà utilizzato in tutte le query mgo, quindi probabilmente non lo si desidera definire direttamente nel modello, ma nel suo derivato da utilizzare solo nelle operazioni di 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})