使用空值更新数据库,同时保留其他列中的值

问题描述 投票:0回答:1

我正在开发 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,
})

Zero values

我后来在Bun ORM中遇到了这个方法:省略零值。这允许我只更新 avatar 列,并且 ORM 忽略结构中的空字段。 但是我无法将头像列重置回空字符串,因为它将被忽略。

我已经尝试了几件事,很可能真的是过度设计了。因为我绝望了,所以我什至尝试过反思。

  1. 尝试将非空的 User 结构字段转换为
    map[string]interface{}
    ,并将其传递给
    Model
    方法。不幸的是,由于我使用了映射,ORM 没有将我的类型转换为它们在我的 User 结构中定义的方式。
  2. 我尝试将旧结构与包含我想要更新的数据的结构合并,这最初有效,但非常hacky,我不喜欢使用它作为解决方案。
  3. 我尝试使用像
    *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(),
})
postgresql go bun-orm
1个回答
0
投票

我认为您正在寻找的东西(如果您还没有找到的话)正在使用类似以下的东西。如果将其分解,您可以有条件地将值添加到

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]

© www.soinside.com 2019 - 2024. All rights reserved.