I want to create a function to update a specific document in MongoDB by it's id but only update the fields if the new provided value is not the Go default.
This is the document struct which I store in MongoDB:
type User struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Username string `json:"username" bson:"username"`
FirstName string `json:"firstName" bson:"first_name"`
LastName string `json:"lastName,omitempty" bson:"last_name,omitempty"`
Email string `json:"email" bson:"email"`
Password string `json:"password,omitempty" bson:"password"`
PhoneNumber string `json:"phoneNumber,omitempty" bson:"phone_number,omitempty"`
Picture string `json:"picture,omitempty" bson:"picture,omitempty"`
Role Role `json:"role" bson:"role"`
}
My update function gets the id of the user document to update and a user struct with only the fields provided which should get updated. So if only the username should get updated all other fields in the provided user struct will have their default value.
I now need to first check if for example the new username is not empty and only then include it on the new update document.
This is how I would solve it in javsacript. Is there a similar solution for Go?
{
...(username && { username: username }),
...(email && { email: email }),
...(firstname && { firstname: firstname }),
...(lastname && { lastname: lastname }),
...(phone && { phone: phone }),
...(picture && { picture: picture }),
},
This is my Update function:
func (us *userQuery) Update(userId string, u datastruct.User) (*datastruct.User, error) {
userCollection := DB.Collection(datastruct.UserCollectionName)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
_id, err := primitive.ObjectIDFromHex(userId)
if err != nil {
return nil, err
}
update := bson.D{{
Key: "$set",
Value: bson.D{
{Key: "username", Value: u.Username}, // only include a field if provided value is not the default
{Key: "firstName", Value: u.FirstName},
{Key: "lastName", Value: u.LastName},
{Key: "email", Value: u.Email},
{Key: "password", Value: u.Password},
{Key: "phoneNumber", Value: u.PhoneNumber},
{Key: "picture", Value: u.Picture},
},
}}
var result datastruct.User
res, err := userCollection.UpdateByID(
ctx,
_id,
update,
)
if err != nil {
return nil, err
}
return &result, nil
}
CodePudding user response:
You have to build the update clause dynamically:
value:=bson.M{}
if len(u.UserName)!=0 {
value["username"]=u.UserName
}
if len(u.FirstName)!=0 {
value["firstName"]=u.FirstName
}
...
if len(value)>0 { // Is there anything to update?
res, err := userCollection.UpdateByID(
ctx,
_id,
bson.M{"$set":value})
}
