Reputation: 1174
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:
How can I user mongo.Collection.BulkWrite()
? I can't find obvious explanation how to put slice of objects into it.
How do mongo decides what is new, what is old and has to be updated? According to _id
?
Upvotes: 9
Views: 10748
Reputation: 2065
Anybody looking for a solution to update particular key:value of a collection of documents,
This will also create a new document if that field doesn't exist.
func UpdateData(data []User) {
upsert := true
after := options.After
collection := client.Database("dbname").Collection("colname")
for _, user := range data {
// Create the search filter
filter := bson.M{"name": user.Name}
// Create the update
update := bson.M{
"$set": bson.M{"AccountId": user.AccountID}, // New Account ID
}
// Create an instance of an options and set the desired options.
opt := options.FindOneAndUpdateOptions{
ReturnDocument: &after,
Upsert: &upsert,
}
// Find one result and update it
result := collection.FindOneAndUpdate(context.Background(), filter, update, &opt)
if result.Err() != nil {
log.Printf("user account id update failed: %v\n", result.Err())
}
}
}
Argument data []User assumes you have a slice of structures with new values to be updated in the database.
Upvotes: 0
Reputation: 18835
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:
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.
Upvotes: 16