MongoDB Golang驱动程序仅更新提供了非空值的字段。

huangapple go评论88阅读模式
英文:

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>



huangapple
  • 本文由 发表于 2022年1月31日 03:31:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/70918176.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定