Golang GORM通过联接表检索多对多关系的数据

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

Golang GORM data retrieve for many to many relationship with join table

问题

我正在使用golang 1.19和GORM作为ORM。我需要使用类别ID检索产品。产品表和类别表通过多对多关系绑定。所以第三个表是product_categories。

我需要做的是当收到带有类别ID的GET请求时,我需要检索具有该类别ID的产品。

以下是模型结构:

// 产品模型
// 类别多对多:product_categories

type Product struct {
	ID               uint           `gorm:"primarykey" json:"id"`
	Slug             string         `gorm:"unique;size:255;" json:"slug"`
	Title            string         `gorm:"size:255;not null" json:"title"`
	Code             string         `gorm:"size:255;not null" json:"code"`
	BrandID          uint           `json:"-"`
	Brand            Brand          `json:"brand"`
	ShortDescription string         `gorm:"not null" json:"short_description"`
	Description      string         `json:"description"`
	Price            uint           `gorm:"not null" json:"price"`
	Quantity         uint           `json:"qnt"`
	DiscountPrice    uint           `json:"discount_price"`
	Categories       []Category     `gorm:"many2many:product_categories;" json:"categories"`
	Attributes       []Attribute    `json:"attributes"`
	ProductImages    []ProductImage `json:"product_images"`
	CreatedAt        time.Time      `json:"-"`
	UpdatedAt        time.Time      `json:"-"`
}
// 类别模型
// 产品多对多:product_categories

type Category struct {
	ID        uint      `gorm:"primarykey" json:"id"`
	Name      string    `gorm:"size:255;not null" json:"name"`
	Icon      string    `gorm:"size:255;not null" json:"icon"`
	Image     string    `gorm:"size:255;not null" json:"image"`
	Weight    int32     `gorm:"AUTO_INCREMENT" json:"weight"`
	Products  []Product `gorm:"many2many:product_categories;" json:"products"`
	CreatedAt time.Time `json:"-"`
	UpdatedAt time.Time `json:"-"`
}

// ProductCategory模型
// 这个表是由gorm自动生成的

type ProductCategory struct {
	CategoryID int  `gorm:"primaryKey" json:"-"`
	ProductID  uint `gorm:"primaryKey" json:"-"`
}

我正在使用另一种方法来完成这个技巧。它运行良好,但我认为在处理多对多关系时,这不是最好的方法。我首先检索ProductCategory,然后循环它并获取product id,然后将其添加到切片中,然后使用这些产品id检索products

以下是我的代码:

func (q *Queries) GetProductsbyCat(id uint) ([]models.Product, error) {
	// 定义products变量和product_cat变量
	products := []models.Product{}
	product_cats := []models.ProductCategory{}

	// 检索product_cat并分配给变量
	err := q.Model(&product_cats).Limit(10).Find(&product_cats, "category_id = ?", id).Error
	if err != nil {
		// 返回空对象和错误。
		return nil, err
	}

	// 定义产品id切片
	productIds := []int{}
	// 循环产品类别并将产品id添加到productids变量中
	for _, v := range product_cats {
		productIds = append(productIds, int(v.ProductID))
	}

	// 检索产品
	err = q.Model(&products).Order("id desc").Preload("ProductImages").Find(&products, productIds).Error
	if err != nil {
		// 返回空对象和错误。
		return nil, err
	}

	return products, nil
}

在我的情况下,使用GORM和多对多关系获取产品的最佳方法是什么?

英文:

I'm using golang 1.19 and ORM as GORM. I need to retrieve products using category id. Products table and categories table bind with many to many relationship. So 3rd table is product_categories.

What I need to do is when get request come with category id, I need to retrieve products with that category id.

Look below for model structer,

// Product model
// Categories many2many:product_categories

type Product struct {
	ID               uint           `gorm:"primarykey" json:"id"`
	Slug             string         `gorm:"unique;size:255;" json:"slug"`
	Title            string         `gorm:"size:255;not null" json:"title"`
	Code             string         `gorm:"size:255;not null" json:"code"`
	BrandID          uint           `json:"-"`
	Brand            Brand          `json:"brand"`
	ShortDescription string         `gorm:"not null" json:"short_description"`
	Description      string         `json:"description"`
	Price            uint           `gorm:"not null" json:"price"`
	Quantity         uint           `json:"qnt"`
	DiscountPrice    uint           `json:"discount_price"`
	Categories       []Category     `gorm:"many2many:product_categories;" json:"categories"`
	Attributes       []Attribute    `json:"attributes"`
	ProductImages    []ProductImage `json:"product_images"`
	CreatedAt        time.Time      `json:"-"`
	UpdatedAt        time.Time      `json:"-"`
}
// Category model
// Products many2many:product_categories

type Category struct {
	ID        uint      `gorm:"primarykey" json:"id"`
	Name      string    `gorm:"size:255;not null" json:"name"`
	Icon      string    `gorm:"size:255;not null" json:"icon"`
	Image     string    `gorm:"size:255;not null" json:"image"`
	Weight    int32     `gorm:"AUTO_INCREMENT" json:"weight"`
	Products  []Product `gorm:"many2many:product_categories;" json:"products"`
	CreatedAt time.Time `json:"-"`
	UpdatedAt time.Time `json:"-"`
}

// ProductCategory Model
// This table auto generate with gorm

type ProductCategory struct {
	CategoryID int  `gorm:"primaryKey" json:"-"`
	ProductID  uint `gorm:"primaryKey" json:"-"`
}

I'm using alternative way to do the trick. It works fine but I think it's not the best way to do it when it comes to many to many. I firstly retrieve ProductCategory then loop it and get product id then add it to slice and after retrieve products using those product id's.

Look below for my codes,

func (q *Queries) GetProductsbyCat(id uint) ([]models.Product, error) {
	// Define products variable and product_cat variable
	products := []models.Product{}
	product_cats := []models.ProductCategory{}

	// Retrieve product_cat and assigned to variable
	err := q.Model(&product_cats).Limit(10).Find(&product_cats, "category_id = ?", id).Error
	if err != nil {
		// Return empty object and error.
		return nil, err
	}

	// define products ids slice
	productIds := []int{}
	// loop product cats and append product id's to productids variable
	for _, v := range product_cats {
		productIds = append(productIds, int(v.ProductID))
	}

	// Retrieve products
	err = q.Model(&products).Order("id desc").Preload("ProductImages").Find(&products, productIds).Error
	if err != nil {
		// Return empty object and error.
		return nil, err
	}

	return products, nil
}

What's the best way to get products for my scenario using many to many relationship with GORM?

答案1

得分: 1

根据 https://gorm.io/docs/many_to_many.html 和预加载的概念,我无法进行验证,因为我没有为此设置,但你应该能够创建一个具有所需ID的类别实体,然后在该类别上预加载产品,类似于:

category := models.Category{ID: id}
err := q.Model(&Category{}).Preload("Products").Find(&category)
英文:

I am not able to validate, as I don't have a setup for this, but based on https://gorm.io/docs/many_to_many.html and the idea of preloading, you should be able to create a category entity with the required ID, then preload products on that category, something like:

category := models.Category{ID: id}
err := q.Model(&Category{}).Preload("Products").Find(&category)

huangapple
  • 本文由 发表于 2022年12月17日 01:24:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/74827833.html
匿名

发表评论

匿名网友

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

确定