Gorm的Has Many关系在关联期间无法添加多个模型实例。

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

Gorm Has Many relationship can't append more than one model instance during association

问题

摘要

主要问题:在gorm中,我可以在hasMany关系中追加多个模型实例吗?还是应该使用ManyToMany关系?例如,Product模型将具有多个Image模型实例。
以下是相关的模型:

type Publication struct {
    ID        string    `gorm:"not null"`
    CreatedAt time.Time `sql:"DEFAULT:CURRENT_TIMESTAMP" json:"created_at"`
    UpdatedAt time.Time `sql:"DEFAULT:CURRENT_TIMESTAMP" json:"updated_at"`
    Views     uint64    `gorm:"default:0" json:"views"`
    Product   Product   `gorm:"foreignkey:ID" json:"product"`
}

type Product struct {
    ID     string         `gorm:"not null"`
    Title  string
    Price  uint64
    Images []ProductImage `gorm:"foreignkey:ID" json:"images"`
}

type ProductImage struct {
    ID   string
    Name string
}

在服务器初始化期间,我以以下方式创建、关联和加载一些数据到MySQL数据库:

err = db.Debug().Model(&models.Product{}).Create(&mk_list_products[i]).Error
if err != nil {
    log.Fatal(err)
}
err = db.Debug().Model(&models.Publication{}).Create(&mk_list_publications[i]).Error
if err != nil {
    log.Fatal(err)
}
err = db.Debug().Model(&mk_list_products[i]).Association("Images").Append(&product_images)
if err != nil {
    log.Fatal(err)
}

我使用以下方式查询具有Product AssociationPublication模型:

pbs := []models.Publication{}
err = db.
    Debug().
    Preload("Product.Images").
    Model(&models.Publication{}).
    Limit(3).
    Where("created_at <= ?", time.Now()).
    Find(&pbs).Error
if err != nil {
    console.Pretty(err)
    return
}

对于ID=3Publication(与其他相似),我得到:

{
    "ID": "3",
    "created_at": "2022-01-06T21:26:41.585-06:00",
    "updated_at": "2022-01-07T21:26:42.154-06:00",
    "views": 0,
    "product": {
        "ID": "3",
        "Title": "Product Title A",
        "Price": 200,
        "category": {
            "ID": "",
            "Parent": "",
            "Image": "",
            "Order": 0,
            "Name": "",
            "Description": "",
            "Slug": ""
        },
        "State": "",
        "Description": "Some Description",
        "Availability": "",
        "Brand": "Some Brand",
        "labels": null,
        "SKU": "Some SKU",
        "images": [
            {
                "ID": "3",
                "Name": "/path/cannabis_product_1.png"
            }
        ]
    }
}

期望的结果

{
    "ID": "3",
    "created_at": "2022-01-06T21:26:41.585-06:00",
    "updated_at": "2022-01-07T21:26:42.154-06:00",
    "views": 0,
    "product": {
        "ID": "3",
        "Title": "Product Title A",
        "Price": 200,
        "category": {
            "ID": "",
            "Parent": "",
            "Image": "",
            "Order": 0,
            "Name": "",
            "Description": "",
            "Slug": ""
        },
        "State": "",
        "Description": "Some Description",
        "Availability": "",
        "Brand": "Some Brand",
        "labels": null,
        "SKU": "Some SKU",
        "images": [
            {
                "ID": "2",
                "Name": "/path/cannabis_product_2.png"
            },
            {
                "ID": "3",
                "Name": "/path/cannabis_product_3.png"
            }
        ]
    }
}
英文:

Summary

Main question: Can I append more than one model instance in a hasMany relationship in gorm or should I use a ManyToMany relationship? E.g. A Product model would have more than one Image model instance.
Here are the relevant models:

type Publication struct {
	ID        string    `gorm:&quot;not null&quot;`
	CreatedAt time.Time `sql:&quot;DEFAULT:CURRENT_TIMESTAMP&quot; json:&quot;created_at&quot;`
	UpdatedAt time.Time `sql:&quot;DEFAULT:CURRENT_TIMESTAMP&quot; json:&quot;updated_at&quot;`
	Views     uint64    `gorm:&quot;default:0&quot; json:&quot;views&quot;`
	Product Product `gorm:&quot;foreignkey:ID&quot; json:&quot;product&quot;`
}
type Product struct {
	ID           string `gorm:&quot;not null&quot;`
	Title        string
	Price        uint64
	Images       []ProductImage `gorm:&quot;foreignkey:ID&quot; json:&quot;images&quot;`
}
type ProductImage struct {
	ID   string
	Name string
}

During Server Initialization, I create, associate and load some data to the MySQL DB in the following way:

err = db.Debug().Model(&amp;models.Product{}).Create(&amp;mk_list_products[i]).Error
		if err != nil {
			log.Fatal(err)
		}
		err = db.Debug().Model(&amp;models.Publication{}).Create(&amp;mk_list_publications[i]).Error
		if err != nil {
			log.Fatal(err)
		}
		err = db.Debug().Model(&amp;mk_list_products[i]).Association(&quot;Images&quot;).Append(&amp;product_images)
		if err != nil {
			log.Fatal(err)
		}

I'm querying Publication model with Product Association as follow:

pbs := []models.Publication{}
	err = db.
		Debug().
		Preload(&quot;Product.Images&quot;).
		Model(&amp;models.Publication{}).
		Limit(3).
		Where(&quot;created_at &lt;= ?&quot;, time.Now()).
		Find(&amp;pbs).Error
	if err != nil {
		console.Pretty(err)
		return
	}

For Publication with ID=3 (similar with the rest) I get

{
&quot;ID&quot;: &quot;3&quot;,
&quot;created_at&quot;: &quot;2022-01-06T21:26:41.585-06:00&quot;,
&quot;updated_at&quot;: &quot;2022-01-07T21:26:42.154-06:00&quot;,
&quot;views&quot;: 0,
&quot;product&quot;: {
&quot;ID&quot;: &quot;3&quot;,
&quot;Title&quot;: &quot;Product Title A&quot;,
&quot;Price&quot;: 200,
&quot;category&quot;: {
&quot;ID&quot;: &quot;&quot;,
&quot;Parent&quot;: &quot;&quot;,
&quot;Image&quot;: &quot;&quot;,
&quot;Order&quot;: 0,
&quot;Name&quot;: &quot;&quot;,
&quot;Description&quot;: &quot;&quot;,
&quot;Slug&quot;: &quot;&quot;
},
&quot;State&quot;: &quot;&quot;,
&quot;Description&quot;: &quot;Some Description&quot;,
&quot;Availability&quot;: &quot;&quot;,
&quot;Brand&quot;: &quot;Some Brand&quot;,
&quot;labels&quot;: null,
&quot;SKU&quot;: &quot;Some SKU&quot;,
&quot;images&quot;: [
{
&quot;ID&quot;: &quot;3&quot;,
&quot;Name&quot;: &quot;/path/cannabis_product_1.png&quot;
}
]
}

Expected result

    {
    &quot;ID&quot;: &quot;3&quot;,
    &quot;created_at&quot;: &quot;2022-01-06T21:26:41.585-06:00&quot;,
    &quot;updated_at&quot;: &quot;2022-01-07T21:26:42.154-06:00&quot;,
    &quot;views&quot;: 0,
    &quot;product&quot;: {
    &quot;ID&quot;: &quot;3&quot;,
    &quot;Title&quot;: &quot;Product Title A&quot;,
    &quot;Price&quot;: 200,
    &quot;category&quot;: {
    &quot;ID&quot;: &quot;&quot;,
    &quot;Parent&quot;: &quot;&quot;,
    &quot;Image&quot;: &quot;&quot;,
    &quot;Order&quot;: 0,
    &quot;Name&quot;: &quot;&quot;,
    &quot;Description&quot;: &quot;&quot;,
    &quot;Slug&quot;: &quot;&quot;
    },
    &quot;State&quot;: &quot;&quot;,
    &quot;Description&quot;: &quot;Some Description&quot;,
    &quot;Availability&quot;: &quot;&quot;,
    &quot;Brand&quot;: &quot;Some Brand&quot;,
    &quot;labels&quot;: null,
    &quot;SKU&quot;: &quot;Some SKU&quot;,
    &quot;images&quot;: [
{
    &quot;ID&quot;: &quot;2&quot;,
    &quot;Name&quot;: &quot;/path/cannabis_product_2.png&quot;
    }    
{
    &quot;ID&quot;: &quot;3&quot;,
    &quot;Name&quot;: &quot;Name&quot;: &quot;/path/cannabis_product_3.png&quot;&quot;
    }
    ]
    }

答案1

得分: 1

解决方案

我仍然不明白为什么在 Product 模型上将 ImageProductID 声明为外键会产生意外的结果。
为了使其工作,我不得不在产品的 Images 字段上定义并添加一个与 ID 不同的 foreignKey

type Product struct {
    ID           string `gorm:"not null"`
    Title        string
    Price        uint64
    ...
    Images       []ProductImage `gorm:"foreignkey:ProductId" json:"images"`
}

然后,在 ProductImage 模型上添加了一个额外的字段 ProductId

type ProductImage struct {
    ID        string
    ProductId string
    Name      string
}

在将两个测试的 ProductImage 实例追加到 PublicationID=3 后,我得到了预期的结果。

err = db.Debug().Model(&mk_list_products[2]).Association("Images").Append(&product_images[2], &product_images[3])
    if err != nil {
        log.Fatal(err)
    }
...
{
"ID": "3",
"created_at": "2022-01-07T11:20:32.298-06:00",
"updated_at": "2022-01-08T11:20:32.867-06:00",
"views": 0,
"product": {
"ID": "3",
"Title": "Product Title 3",
"Price": 200,
"category": {
"ID": "",
"Parent": "",
"Image": "",
"Order": 0,
"Name": "",
"Description": "",
"Slug": ""
},
"State": "",
"Description": "Some Description",
"Availability": "",
"Brand": "Some Brand",
"labels": null,
"SKU": "Some SKU",
"images": [
{
"ID": "3",
"ProductId": "3",
"Name": "/path/cannabis_product_3.png"
},
{
"ID": "4",
"ProductId": "3",
"Name": "/path/cannabis_product_4.png"
}
]
}
}
英文:

Solution

I still don't understand why declaring the ID of ImageProduct as the foreign on the Product model gives unexpected result.
To make this work, I had to defined and add a different foreignKey other than ID on product Imagesfield

type Product struct {
	ID           string `gorm:&quot;not null&quot;`
	Title        string
	Price        uint64
    ...
	Images       []ProductImage `gorm:&quot;foreignkey:ProductId&quot; json:&quot;images&quot;`
}

Then, on the ProductImage model I added an additional field ProductId

type ProductImage struct {
    ID        string
    ProductId string
    Name      string
}

After appending two test ProductImage instances to Publication with ID=3 I get the expected result.

err = db.Debug().Model(&amp;mk_list_products[2]).Association(&quot;Images&quot;).Append(&amp;product_images[2], &amp;product_images[3])
	if err != nil {
		log.Fatal(err)
	}
...
{
&quot;ID&quot;: &quot;3&quot;,
&quot;created_at&quot;: &quot;2022-01-07T11:20:32.298-06:00&quot;,
&quot;updated_at&quot;: &quot;2022-01-08T11:20:32.867-06:00&quot;,
&quot;views&quot;: 0,
&quot;product&quot;: {
&quot;ID&quot;: &quot;3&quot;,
&quot;Title&quot;: &quot;Product Title 3&quot;,
&quot;Price&quot;: 200,
&quot;category&quot;: {
&quot;ID&quot;: &quot;&quot;,
&quot;Parent&quot;: &quot;&quot;,
&quot;Image&quot;: &quot;&quot;,
&quot;Order&quot;: 0,
&quot;Name&quot;: &quot;&quot;,
&quot;Description&quot;: &quot;&quot;,
&quot;Slug&quot;: &quot;&quot;
},
&quot;State&quot;: &quot;&quot;,
&quot;Description&quot;: &quot;Some Description&quot;,
&quot;Availability&quot;: &quot;&quot;,
&quot;Brand&quot;: &quot;Some Brand&quot;,
&quot;labels&quot;: null,
&quot;SKU&quot;: &quot;Some SKU&quot;,
&quot;images&quot;: [
{
&quot;ID&quot;: &quot;3&quot;,
&quot;ProductId&quot;: &quot;3&quot;,
&quot;Name&quot;: &quot;/path/cannabis_product_3.png&quot;
},
{
&quot;ID&quot;: &quot;4&quot;,
&quot;ProductId&quot;: &quot;3&quot;,
&quot;Name&quot;: &quot;/path/cannabis_product_4.png&quot;
}
]
}
}

huangapple
  • 本文由 发表于 2022年1月8日 11:49:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/70629474.html
匿名

发表评论

匿名网友

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

确定