英文:
MongoDB Golang Driver only update fields were provided value is not empty
问题
我想创建一个函数,通过id更新MongoDB中的特定文档,但只有在新提供的值不是Go的默认值时才更新字段。
这是我存储在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"`
}
我的更新函数接收要更新的用户文档的id和一个只包含要更新字段的用户结构。所以如果只有用户名应该被更新,提供的用户结构中的所有其他字段将具有它们的默认值。
现在,我需要首先检查例如新用户名是否不为空,只有在这种情况下才将其包含在新的更新文档中。
这是我在JavaScript中的解决方案。Go语言中是否有类似的解决方案?
{
...(username && { username: username }),
...(email && { email: email }),
...(firstname && { firstname: firstname }),
...(lastname && { lastname: lastname }),
...(phone && { phone: phone }),
...(picture && { picture: picture }),
}
这是我的Update函数:
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
}
英文:
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
}
答案1
得分: 0
你必须动态构建更新语句:
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 { // 是否有需要更新的内容?
res, err := userCollection.UpdateByID(
ctx,
_id,
bson.M{"$set": value})
}
英文:
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})
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论