Search code examples
mongodbgomgomongo-go

Using FindAndModify to run queries in the official Mongo Go Driver


In the community driven Mongo driver for Go, i.e. Mgo, we can use the Apply API call to run MongoDB queries involving $set or $inc. An example of this use-case in Mgo is as follows:

change := mgo.Change{
    Update:    bson.M{"$set": bson.M{"phone": "+55 53 8402 8510"}},
    ReturnNew: true,
}
_, err = MongoSession.DB("test").C("people").Find(bson.M{"_id": a}).Apply(change, &result)

Quoting the official documentation for this API call:

Apply runs the findAndModify MongoDB command, which allows updating, upserting or removing a document matching a query and atomically returning either the old version (the default) or the new version of the document (when ReturnNew is true).

I am currently working on porting a project from Mgo to the official Mongo Go driver. However, I am unable to find any method that runs the findAndModify command to achieve a similar use-case. For replacing the Apply API with a relevant method from the official driver, what would be the recommended approach?

I have considered examining the query under 'Update' in the existing code, and manually using the Find/Update/Replace methods provided in the official driver. But, would there be any better way to do the same?


Solution

  • I was able to solve this using the FindOneAndUpdate API.

    It internally uses FindAndModify, even though it is not explicitly mentioned in the documentations. Code I used to emulate this feature of Mgo in Go's Mongo Driver is as follows:

    MongoSession, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        panic(err)
    }
    ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
    err = MongoSession.Connect(ctx)
    collection := MongoSession.Database("test").Collection("people")
    a, err := primitive.ObjectIDFromHex("XXXXXXXXXX") //hiding hex value
    b := collection.FindOneAndUpdate(ctx, bson.M{"_id": a}, bson.M{"$set": bson.M{"phone": "Replacing using the query"}})
    

    Edit (29/02/20): It looks like after this answer, the MongoDB Engineers have updated the documentation about the MongoDB functionality being used. The documentation now states that FindOneAndUpdate uses the findAndModify operation.