如何使用gorm获取双重嵌套数据?

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

How to get double nested data with gorm?

问题

我正在开发一个使用Go和GORM管理报价的应用程序。用户可以创建报价,报价可以有多个标签,用户可以将报价添加到收藏夹中。

我想要获取用户添加到收藏夹中的报价列表,并且在那个时候,我想要获取与报价相关联的标签。

这是我的数据模型:

type Quote struct {
	ID            int       `gorm:"primary_key" json:"id"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
	Text          string    `json:"text"`
	Page          int       `json:"page"`
	Published     bool      `gorm:"default:false" json:"published"`
	Tags          []Tag     `gorm:"many2many:quotes_tags;" json:"tags"`
	User          User      `json:"user"`
	UserID        string    `json:"user_id"`
	FavoriteUsers []User    `gorm:"many2many:users_quotes;" json:"favorite_users"`
}

type User struct {
	ID              string    `json:"id"`
	CreatedAt       time.Time `json:"created_at"`
	UpdatedAt       time.Time `json:"updated_at"`
	Username        string    `json:"username"`
	Quotes          []Quote   `json:"quotes"`
	FavoriteQuotes  []Quote   `gorm:"many2many:users_quotes;" json:"favorite_quotes"`
}

type Tag struct {
	ID        int       `gorm:"primary_key" json:"id"`
	CreatedAt time.Time `json:"created_at"`
	Name      string    `json:"name"`
}

我尝试了以下代码,成功获取了收藏的报价,但是标签为空。有没有办法使用GORM来实现这个功能?非常感谢。

func (service *Service) GetUser(uid string) (models.User, error) {
	fmt.Println(uid)
	user := models.User{}
	if result := service.db.Preload(clause.Associations).First(&user, "id = ?", uid); result.Error != nil {
		return models.User{}, result.Error
	}
	return user, nil
}

func (service *Service) GetFavoriteQuotes(uid string) ([]models.Quote, error) {
	user, err := service.GetUser(uid)
	if err != nil {
		return []models.Quote{}, err
	}
	return user.FavoriteQuotes, nil
}
英文:

I am developing an application that manages quotes using go and gorm. Users create quote, quotes have multiple tags, and users can add quotes to their favorites.

I want to get a list of quotes that a user has added to their favorites. And at that time, I want to get the tag attached to the quotes.

Here is my data models.

type Quote struct {
	ID            int       `gorm:"primary_key" json:"id"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
	Text          string    `json:"text"`
	Page          int       `json:"page"`
	Published     bool      `gorm:"default:false" json:"published"`
	Tags          []Tag     `gorm:"many2many:quotes_tags;" json:"tags"`
	User          User      `json:"user"`
	UserID        string    `json:"user_id"`
	FavoriteUsers []User    `gorm:"many2many:users_quotes;" json:"favorite_users"`
}

type User struct {
	ID              string    `json:"id"`
	CreatedAt       time.Time `json:"created_at"`
	UpdatedAt       time.Time `json:"updated_at"`
	Username        string    `json:"username"`
	Quotes          []Quote   `json:"quotes"`
	FavoriteQuotes  []Quote   `gorm:"many2many:users_quotes;" json:"favorite_quotes"`
}

type Tag struct {
	ID        int       `gorm:"primary_key" json:"id"`
	CreatedAt time.Time `json:"created_at"`
	Name      string    `json:"name"`
}

I tried the following and got the favorite quote, but the tags was null. Is there a way to do this with gorm? Thank you in advance.

func (service *Service) GetUser(uid string) (models.User, error) {
	fmt.Println(uid)
	user := models.User{}
	if result := service.db.Preload(clause.Associations).First(&user, "id = ?", uid); result.Error != nil {
		return models.User{}, result.Error
	}
	return user, nil
}

func (service *Service) GetFavoriteQuotes(uid string) ([]models.Quote, error) {
	user, err := service.GetUser(uid)
	if err != nil {
		return []models.Quote{}, err
	}
	return user.FavoriteQuotes, nil
}

答案1

得分: 1

如果你查看Preload All文档,它说:

clause.Associations不会预加载嵌套关联,但你可以与Nested Preloading一起使用。

在你的情况下,代码应该是这样的:

if result := service.db.Preload("FavoriteQuotes.Tags").Preload(clause.Associations).First(&user, "id = ?", uid); result.Error != nil {
    return models.User{}, result.Error
}
英文:

If you check the Preload All documentation, it says:

> clause.Associations won’t preload nested associations, but you can use it with Nested Preloading

In your case, this would be something like this:

if result := service.db.Preload("FavoriteQuotes.Tags").Preload(clause.Associations).First(&user, "id = ?", uid); result.Error != nil {
        return models.User{}, result.Error
    }

huangapple
  • 本文由 发表于 2021年5月19日 23:14:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/67606015.html
匿名

发表评论

匿名网友

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

确定