更新字段将创建新的外键项,而不是对其进行更新

时间:2018-08-21 11:26:19

标签: postgresql go go-gorm

我与Postgresql建立了一对一的关系,即位置:

type App struct {
    gorm.Model

    PersoID      string `gorm:"primary_key;unique" json:"perso_id"`

    Location   OllyLocation `gorm:"foreignkey:location_id"`
    LocationID *uint        `json:"-" gorm:"type:integer REFERENCES locations(id)"`

    Users          []User       `json:"users,omitempty" gorm:"many2many:app_users;"`
}

type Location struct {
    ID        uint      `json:"-" gorm:"primary_key;unique"`
    CreatedAt time.Time `json:"-"`
    UpdatedAt time.Time

    Lat         float64 `json:"lat"`
    Long        float64 `json:"long"`
    Address     string  `json:"address"`
    Country     string  `json:"country"`
}

但是,正如您所看到的,App结构具有其自己的primaryKey id作为字符串(和GORM一个)。 这样就阻止了从gorm执行简单的db.Save()

所以我尝试做:

func (previousModel *App) UpdateAndReturnedUpdated(db *gorm.DB, appUpdated *App) error {
    if err := db.Model(previousModel).Update(appUpdated).Error; err != nil {
        return err
    }

    return db.Preload("Location").First(previousModel, App{PersoID: appUpdated.PersoID}).Error
}

由此,该应用程序已正确更新-太棒了! -但不是位置。

使用新值在数据库中重新创建位置,并在应用程序上更新ForeignKey LocationID。

这很烦人,因为如果我只想更新地址而不指定其他字段,那么它们将使用原始类型值(纬度/经度将为0)重新创建

关于如何更新ForeignKey的任何想法?谢谢!

2 个答案:

答案 0 :(得分:1)

您可以使用它修改关联的实体

db.Set("gorm:save_associations", false).Save(previousModel)

或仅保存结构的一个字段

db.Model(previousModel).UpdateColumn("PersoID", appUpdated.PersoID)

如果要更新关联的实体而不是关系 您将需要更新实体本身

db.Model(Location{ID:*previousModel.LocationID}).Update(appUpdated.Location)

答案 1 :(得分:0)

再一次(但不要怪他,一个人),主要问题来自文档不完整。

当我检查我是否正确地预加载了外来对象并指明其ID(阻止了ForeignKey是插入而不是更新的事实)时,所有问题都得到解决

然后,为了能够正确更新它,我必须做:

const arr = [{
  name: 'John',
  email: 'johnson@mail.com',
  age: 25,
  address: 'USA'
}, {
  name: 'Tom',
  email: 'tom@mail.com',
  age: 35,
  address: 'England'
}, {
  name: 'Mark',
  email: 'mark@mail.com',
  age: 28,
  address: 'England'
}];

const selectedNames = ["Mark", "Tom"];

const result = arr.filter(({
  name
}) => selectedNames.includes(name));

console.log(result);

非常痛苦,但至少已经解决了。