MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mgo-Upsert-Operation anpassen

Zur Beantwortung der „Meine eigentliche Frage:Wie kann ich das Verhalten von mgo vor dem Upsert anpassen? " - Sie können das bson-Marshalling anpassen, indem Sie bson Getter definieren zum Modell.

Um zu veranschaulichen, wie es funktioniert, vereinfachen wir das Modell, um verschachtelte Dokumente zu vermeiden:

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

Mit newGame wie folgt:

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

Das Update col.UpsertId(newGame.ID, newGame) standardmäßig marshallt newGame in JSON und erzeugt eine Mongo-Abfrage wie:

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

Verwendung von $set , $push usw. können Sie einen benutzerdefinierten bson-Getter definieren. Z. B.

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
}

Also das Update col.UpsertId(newGame.ID, newGame) erzeugt eine Mongodb-Abfrage

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

Um es deutlich zu machen – der benutzerdefinierte Marshaller wird in allen mgo-Abfragen verwendet, daher möchten Sie ihn wahrscheinlich nicht direkt für das Modell definieren, sondern für seine Ableitung, die nur in Upsert-Operationen verwendet werden soll:

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})