简体   繁体   English

Golang Gorm 多对多与选择性列

[英]Golang Gorm Many to Many with Selective Column

I'm trying to fetch books data that have many authors.我正在尝试获取具有许多作者的书籍数据。 The relationship type between them is simple Many to Many with a pivot table only consist both ID.它们之间的关系类型是简单的多对多,pivot 表只包含两个 ID。 This is the models,这是模型,

package model

import "gorm.io/gorm"

type Author struct {
    gorm.Model
    ID   uint    `gorm:"primaryKey; autoIncrement" json:"id"`
    Name string  `gorm:"Not Null" json:"name"`
    Book []*Book `gorm:"many2many:trx_book_author;" json:"books"`
}

func (author *Author) TableName() string {
    return "tbl_authors"
}
package model

import "gorm.io/gorm"

type Book struct {
    gorm.Model
    ID          uint      `gorm:"primaryKey; autoIncrement" json:"id"`
    Title       string    `gorm:"Not Null" json:"title"`
    Description string    `json:"description"`
    PageNumber  int       `gorm:"Not Null" json:"page_number"`
    Author      []*Author `gorm:"many2many:trx_book_author;" json:"authors"`
}

func (book *Book) TableName() string {
    return "tbl_books"
}

And this is the way I fetch the data,这就是我获取数据的方式,

func (bookRepository *BookRepository) GetAll() []model.Book {
    var books []model.Book

    bookRepository.db.Preload("Author").Find(&books)

    return books
}

Whenever I hit the URL, I got bunch of data that I wanted but I want to select only 'name' column on author.每当我点击 URL 时,我都会得到一堆我想要的数据,但我想 select只有作者的“名称”列。 回复 I've tried with this solution but it's not working我已经尝试过这个解决方案,但它不起作用

func (bookRepository *BookRepository) GetAll() []model.Book {
    var books []model.Book

    bookRepository.db.Preload("Author", func(tx *gorm.DB) *gorm.DB {
        return tx.Select("name")
    }).Find(&books)

    return books
}

any idea?任何想法?

EDIT 1 : This is the error produced when using tx.Select("name") or ("Name")编辑 1 :这是使用 tx.Select("name") 或 ("Name") 时产生的错误

failed to assign association &model.Author{Model:gorm.Model{ID:0x0, CreatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), UpdatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), DeletedAt:gorm.DeletedAt{Time:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), Valid:false}}, ID:0x0, Name:"dowjqdiq", Book:[]*model.Book(nil)}, make sure foreign fields exists; failed to assign association &model.Author{Model:gorm.Model{ID:0x0, CreatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), UpdatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), DeletedAt:gorm.DeletedAt{Time:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), Valid:false}}, ID:0x0, Name:"ddqw", Book:[]*model.Book(nil)}, make sure foreign fields exists; failed to assign association &model.Author{Model:gorm.Model{ID:0x0, CreatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), UpdatedAt:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), DeletedAt:gorm.DeletedAt{Time:time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC), Valid:false}}, ID:0x0, Name:"vevebe", Book:[]*model.Book(nil)}, make sure foreign fields exists
[24.020ms] [rows:5] SELECT * FROM `tbl_books` WHERE `tbl_books`.`deleted_at` IS NULL

Select a specific field is possible in Preload using Custom Preloading SQL . Select 使用Custom Preloading SQL在预加载中可以使用特定字段。

Create a custom struct with specific fields which you want to fetch from DB.使用要从数据库中获取的特定字段创建自定义结构。

type TempBook struct{
  Field_Name Data_Type
  .
  .
  .

}

db.Model(&Book{}).Preload("Author", func(tx *gorm.DB) *gorm.DB {
return tx.Select("Name")
}).Find(&TempBook{})

If you want to get rid off with error:如果你想摆脱错误:

In such case for "has_many" association you should specify both Foreign Key and Association Foreign Key.在这种情况下,对于“has_many”关联,您应该同时指定外键和关联外键。

Intially add the ForeignKey.最初添加 ForeignKey。 If it still doesn't work then add the AssociationForeignKey.如果它仍然不起作用,请添加 AssociationForeignKey。

Make sure you should specify the ForeignKey inside custom struct like this: gorm:"foreignKey:ID"确保您应该像这样在自定义结构中指定 ForeignKey: gorm:"foreignKey:ID"

For Better understanding refer this link: https://github.com/go-gorm/gorm/issues/4015 and Golang gorm preloading为了更好地理解,请参阅此链接: https://github.com/go-gorm/gorm/issues/4015Golang gorm preloading

Query single column is also possible with Pluck() but sure if it supported by Preload or not.使用Pluck()也可以查询单列,但要确定 Preload 是否支持。

For Pluck you can refer this link: https://gorm.io/docs/advanced_query.html#Pluck对于 Pluck,您可以参考此链接: https://gorm.io/docs/advanced_query.html#Pluck

The issue is in the relationship you are trying to create.问题在于你试图建立的关系。 HasMany in GORM will preload the entity in One To Many relationship. GORM 中的 HasMany 将在一对多关系中预加载实体。

You are looking for Many To Many and a custom preload to fetch the author's name from the third table.您正在寻找多对多和自定义预加载以从第三个表中获取作者的姓名。

I had this issue and this is how I managed to solve it:我遇到了这个问题,这就是我设法解决的方法:

    query.
    Preload("Ingredients", func(db *gorm.DB) *gorm.DB {
        return db.Joins("LEFT JOIN ingredients ON ingredients.id=meal_ingredients.ingredient_id").Select("name, macronutrient, measure, amount, meal_id")
    }).
    Find(&model)

This means preloading the Join table and fetching the Authors name information from another table to preload it in your base model will view the Preload as HasMany and fix the issue for you.这意味着预加载 Join 表并从另一个表中获取 Authors 名称信息以将其预加载到您的基础 model 中,会将 Preload 视为 HasMany 并为您解决问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM