【问题标题】:Go GORM many2many issue去 GORM many2many 问题
【发布时间】:2023-03-04 03:33:01
【问题描述】:

我想不出将关联添加到模型的最佳方法。我有以下结构

type Beer struct {
        ID             uint       `json:"id"`
    Name           string     `json:"name" gorm:"not null;" sql:"unique"`
    Description    string     `json:"description" gorm:"not null;"`
    ImageURL       string     `json:"image_url"`
    AlcoholContent float64    `json:"alcohol_content, default:0"`
    Featured       bool       `json:"featured"`
    BrewStart      time.Time  `json:"brew_start"`
    BrewEnd        time.Time  `json:"brew_end"` 
    Brewers        []Brewer   `gorm:"many2many:beer_brewers" json:"brewers"`
}

type Brewer struct {
    ID        uint       `json:"id"`
    FirstName string     `json:"first_name"`
    LastName  string     `json:"last_name"`
    Title     string     `json:"title"`
    Featured  bool       `json:"featured"`
    Beers     []Beer    `gorm:"many2many:beer_brewers" json:"beers"`
}

以下是我在数据库中播种的数据示例

Beer{
    Name:           "some pale ale",
    Description:    "a description of some pale ale",
    ImageURL:       "http://via.placeholder.com/350x150",
    AlcoholContent: 4.5,
    Featured:       false,
    BrewStart:      utils.ParseTime("30-10-2017 13:00 (AEDT)"),
    BrewEnd:        utils.ParseTime("14-11-2017 13:00 (AEDT)"),
    Brewers: []Brewer{
        Brewer{FirstName: "john", LastName: "smith", Title: "bottle shaker", Featured: false},
        Brewer{FirstName: "joe", LastName: "bloggs", Title: "bottle maker", Featured: true},
    },
},
Beer{
    Name:           "some lager",
    Description:    "a description of some pale ale",
    ImageURL:       "http://via.placeholder.com/350x150",
    AlcoholContent: 4.5,
    Featured:       false,
    BrewStart:      utils.ParseTime("30-10-2017 13:00 (AEDT)"),
    BrewEnd:        utils.ParseTime("14-11-2017 13:00 (AEDT)"),
    Brewers: []Brewer{
        Brewer{FirstName: "john", LastName: "smith", Title: "bottle shaker", Featured: false},
        Brewer{FirstName: "joe", LastName: "bloggs", Title: "bottle maker", Featured: true},
    },
},

但是,上述操作会在 Brewer 表中创建重复的 Brewer。我的问题是,引用已经存在的 Brewer 但不在 Brewer 表中创建另一个 Brewer 项目的最佳方法是什么?..以及将新 Brewer 附加到 Beer 集合中的最佳方法是什么?

谢谢, 贾斯汀

【问题讨论】:

    标签: postgresql go foreign-keys many-to-many go-gorm


    【解决方案1】:

    尝试先创建啤酒,然后创建啤酒,并使用 .append 方法将啤酒添加到啤酒中。

    http://jinzhu.me/gorm/associations.html#association-mode

    // Start Association Mode
    var user User
    db.Model(&user).Association("Languages")
    // `user` is the source, it need to be a valid record (contains primary key)
    // `Languages` is source's field name for a relationship.
    // If those conditions not matched, will return an error, check it with:
    // db.Model(&user).Association("Languages").Error
    
    
    // Query - Find out all related associations
    db.Model(&user).Association("Languages").Find(&languages)
    
    
    // Append - Append new associations for many2many, has_many, will replace current association for has_one, belongs_to
    db.Model(&user).Association("Languages").Append([]Language{languageZH, languageEN})
    db.Model(&user).Association("Languages").Append(Language{Name: "DE"})
    

    【讨论】:

      【解决方案2】:

      所以我想出了一个解决方案来解决我上面想做的事情。要将新的 Brewer 添加到 Beer.Brewers 集合中,我需要执行以下操作,

      brewerr := Brewer{}
          db.Where(&Brewer{FirstName: "justin"}).Find(&brewerr)
      
      beerr := Beer{}
          db.Preload("Brewers").Where(&Beer{Name: "some lager"}).Find(&beerr).Association("Brewers").Append(&brewerr)
      

      请务必注意,我需要先 Preload Beer.Brewers 集合,然后再追加。未能预加载导致追加覆盖该Beer 的所有Brewers

      【讨论】:

      【解决方案3】:

      这里的想法如下 1.您独立创建啤酒厂 2.添加它们时,添加主键字段“BrewerId”,如图所示 3. 这将在 brewers 表中查找 Brewer 并将其添加到 Beer。

      import (
          "time"
      
          "github.com/jinzhu/gorm"
      
          // used by gorm
          _ "github.com/jinzhu/gorm/dialects/postgres"
      )
      
      type Beer struct {
          BeerId         uint      `json:"id"`
          Name           string    `json:"name" gorm:"not null;" sql:"unique"`
          Description    string    `json:"description" gorm:"not null;"`
          ImageURL       string    `json:"image_url"`
          AlcoholContent float64   `json:"alcohol_content, default:0"`
          Featured       bool      `json:"featured"`
          BrewStart      time.Time `json:"brew_start"`
          BrewEnd        time.Time `json:"brew_end"`
          Brewers        []Brewer  `json:"brewers" gorm:"many2many:beer_brewers;association_foreignkey:brewer_id;foreignkey:beer_id"`
      }
      
      type Brewer struct {
          BrewerId  uint   `json:"id"`
          FirstName string `json:"first_name"`
          LastName  string `json:"last_name"`
          Title     string `json:"title"`
          Featured  bool   `json:"featured"`
      }
      
      func migrate() {
          // Connection is the connection string
          connection := "host=%v port=%v user=%v dbname=%v password=%v sslmode=%v connect_timeout=%v"
          db, _ := gorm.Open("postgres", connection)
          db.AutoMigrate(&Beer{}, &Brewer{})
          db.Model(&Beer{}).Related(&Brewer{}, "Brewers")
      
          db.Create(&Brewer{FirstName: "justin"})
          db.Create(&Beer{
              Name:           "some lager",
          Description:    "a description of some pale ale",
          ImageURL:       "http://via.placeholder.com/350x150",
          AlcoholContent: 4.5,
          Featured:       false,
          BrewStart:      utils.ParseTime("30-10-2017 13:00 (AEDT)"),
          BrewEnd:        utils.ParseTime("14-11-2017 13:00 (AEDT)"),
          }).Association("Brewers").Append(&Brewer{BrewerId: 123,})
      }
      

      【讨论】:

        【解决方案4】:

        不确定您是否考虑过此选项 - 更好的方法可能是在您的 Beers.Brewers 字段中保存对(一部分)Brewer ID 的引用。随着数据的编码,您可以将这些 ID 转换为完整的字段值(使用自定义的 marshal 函数)。这可能是合适的,除非您有速度/性能方面的考虑。

        【讨论】:

          猜你喜欢
          • 2020-02-05
          • 2017-06-22
          • 1970-01-01
          • 1970-01-01
          • 2019-12-30
          • 1970-01-01
          • 2012-07-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多