我正在开发 REST API。目前,我一直在创建一个 PATCH 端点来更新用户信息,例如用户名、生日等。我已经被困了几天,试图使用我的 Postgres 数据库更新信息。
我正在使用 Bun ORM https://bun.uptrace.dev/guide/query-update.html 与数据库交互。我遇到的问题源于下面的代码片段:
/* Database Model */
type User struct {
Id uuid.UUID `json:"id,omitempty" bun:"column:pk,type:uuid,default:gen_random_uuid()"`
Email string `json:"email,omitempty"`
Name string `json:"name,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"-" dbKey:"password"`
Verified bool `json:"verified,omitempty"`
EmailVerified bool `json:"emailVerified,omitempty"`
Avatar *string `json:"avatar,omitempty"`
GraduationYear int `json:"graduationYear,omitempty"`
Degree *string `json:"degree,omitempty"`
Major *string `json:"major,omitempty"`
Intrests int `json:"intrests,omitempty"`
Clubs int `json:"clubs,omitempty"`
Sports int `json:"sports,omitempty"`
NotificationId string `json:"notificationId,omitempty"`
CreatedAt time.Time `json:"createdAt,omitempty" bun:"type:timestamp,default:now()"`
UpdatedAt time.Time `json:"updatedAt,omitempty" bun:"type:timestamp,default:now()"`
}
func (r *userRepositoryImpl) UpdateUser(userId string, data models.User) (*models.User, error) {
user := models.User(data)
_, err := r.db.NewUpdate().Model(&user).Where("id = ?", userId).Returning("*").Exec(r.context)
if err != nil {
return nil, err
}
return &user, nil
}
此函数旨在根据我向 User 结构提供的数据来更新用户。但是,如果我只想更新其中一个字段,它会将 Postgres 数据库中的所有列设置为其默认值或零值。示例:
/* This resets all other column values to their default or zero value, just affecting the avatar column */
updatedUser, err := s.userRepository.UpdateUser(userId, models.User{
Avatar: &avatarUrl,
})
我后来在Bun ORM中遇到了这个方法:省略零值。这允许我只更新 avatar 列,并且 ORM 忽略结构中的空字段。 但是我无法将头像列重置回空字符串,因为它将被忽略。
我已经尝试了几件事,很可能真的是过度设计了。因为我绝望了,所以我什至尝试过反思。
map[string]interface{}
,并将其传递给 Model
方法。不幸的是,由于我使用了映射,ORM 没有将我的类型转换为它们在我的 User 结构中定义的方式。*string
这样的指针值来表示空值,但得到的结果与我在文章开头所描述的结果相同。我真的很感谢一些指导和帮助,我觉得我想太多了,我想听听其他人的想法。如果需要额外的说明,我将根据需要编辑这篇文章。
编辑1
/* The request structure that the endpoint can receive. Certain fields may be excluded, since its a PATCH request */
type UpdateDataRequest struct {
Email string `json:"email,omitempty" validate:"omitempty,email"`
Name string `json:"name,omitempty" validate:"omitempty,min=3,max=32"`
Username string `json:"username,omitempty" validate:"omitempty,min=3,max=24"`
GraduationYear int `json:"graduationYear,omitempty" validate:"omitempty,number"`
Degree string `json:"degree,omitempty" validate:"omitempty,min=3,max=32"`
Major string `json:"major,omitempty" validate:"omitempty,min=3,max=32"`
Intrests int `json:"intrests,omitempty" validate:"omitempty,number"`
Clubs int `json:"clubs,omitempty" validate:"omitempty,number"`
Sports int `json:"sports,omitempty" validate:"omitempty,number"`
}
/* Updates the user (From my PATCH enddpoint) */
updatedUser, err := s.userRepository.UpdateUser(userId, models.User{
Email: updateUserData.Email,
Name: updateUserData.Name,
Username: updateUserData.Username,
GraduationYear: updateUserData.GraduationYear,
Degree: &updateUserData.Degree,
Major: &updateUserData.Major,
Intrests: updateUserData.Intrests,
Clubs: updateUserData.Clubs,
Sports: updateUserData.Sports,
UpdatedAt: time.Now(),
})
我认为您正在寻找的东西(如果您还没有找到的话)正在使用类似以下的东西。如果将其分解,您可以有条件地将值添加到
UpdateQuery
返回的 Model(yourModel)
对象,而不是使用方法链接。
db.NewUpdate().
Model(yourModel).
Set("colName ? ", theUpdatedValue).
Set("otherColName ? ", otherUpdatedValue).
... more Set(..)...
Where("yourRow.id = ?", rowId).
Exec(.....etc...)
根据文档 [https://bun.uptrace.dev/guide/query-update.html#example]