Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang. MongoDB bulkWrite() to update slice of documents

Tags:

mongodb

go

I have a slice of objects I want to save to Mongo collection. Let's say

type (
    User struct {
        AccountId       string
        Name            string
        FamilyName      string
        EmailAddress    string
    }
)

func persistUsers(ctx context.Context, db *mongo.Collection, users []User) {

}

Some users are already saved, some - aren't. I want to upsert the slice. Hence I have two question:

  1. How can I user mongo.Collection.BulkWrite()? I can't find obvious explanation how to put slice of objects into it.

  2. How do mongo decides what is new, what is old and has to be updated? According to _id?

like image 735
Yura Avatar asked Oct 24 '19 09:10

Yura


1 Answers

How can I use mongo.Collection.BulkWrite()?

This example code is based on MongoDB Go driver v1.1.2. First you need to import the following:

"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/bson"

And below is the example code for Collection.BulkWrite and utilises your User struct example:

collection := client.Database("databaseName").Collection("collectionName")

var operations []mongo.WriteModel

// Example using User struct
userA := User{AccountId:"1", Name:"John", FamilyName:"Smith", EmailAddress:"[email protected]"}

operationA := mongo.NewUpdateOneModel()
operationA.SetFilter(bson.M{"AccountId": userA.AccountId}) 
operationA.SetUpdate(bson.M{"Name":userA.Name, 
                            "FamilyName":userA.FamilyName, 
                            "EmailAddress":userA.EmailAddress})
// Set Upsert flag option to turn the update operation to upsert
operationA.SetUpsert(true) 
operations = append(operations, operationA)

// Example using bson.M{}
operationB := mongo.NewUpdateOneModel()
operationB.SetFilter(bson.M{"AccountId":2}) 
operationB.SetUpdate(bson.M{"Name":"Jane", 
                              "FamilyName":"Smith", 
                              "EmailAddress":"[email protected]"})
operationB.SetUpsert(true) 
operations = append(operations, operationB)

// Specify an option to turn the bulk insertion in order of operation
bulkOption := options.BulkWriteOptions{}
bulkOption.SetOrdered(true)

result, err := collection.BulkWrite(context.TODO(), operations, &bulkOption)
if err != nil {
        log.Fatal(err)
}
fmt.Println(result)

For more information please see:

  • MongoDB Go driver options.BulkWriteOptions
  • MongoDB Go driver options.UpdateOptions
  • MongoDB db.collection.bulkWrite()

How do mongo decides what is new, what is old and has to be updated?

If there is no document matches the query criteria (the filter), then update() inserts a single document. If there are documents that match the query criteria it becomes an update. See also Upsert Behaviour for more information.

If your update query criteria contains _id with dot notation, please see Upsert With Dotted _id Query.

like image 81
Wan Bachtiar Avatar answered Oct 13 '22 10:10

Wan Bachtiar