using Preload and Join in gorm

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

using Preload and Join in gorm

问题

让我们假设我有以下三个结构体:

type Question struct {
    gorm.Model
    Id            *uint64        `json:"id" gorm:"column=id;primaryKey;autoIncrement"`
    Name          string         `json:"name" gorm:"unique"`
    SkillId       *uint64        `json:"skill_id"`
    TestQuestions []TestQuestion `json:"test_questions"`
}

type Skill struct {
    gorm.Model
    SkillName string     `json:"skill_name"`
    Questions []Question `json:"questions"`
}

type TestQuestion struct {
    gorm.Model
    QuestionId uint64 `json:"question_id"`
    TestId     uint64 `json:"test_id"`
}

我想选择所有的问题,并且对于每个问题,我想选择该问题的技能名称而不是技能ID,并且我想预加载TestQuestion。我尝试创建以下结构体来存储我的结果:

type QuestionResponse struct {
    SkillName     string       `json:"skill_name"`
    Name          string       `json:"name"`
    TestQuestions TestQuestion `json:"test_questions"`
}

我尝试了以下查询:

db.Table("questions").Preload("TestQuestions").
    Joins("inner join skills on questions.skill_id = skills.id").
    Select("questions.name, skills.skill_name, questions.difficulty, questions.max_points, questions.type, questions.expected_time, questions.question_text, questions.file_read_me").
    Find(&question)

但是我得到了这个错误:"invalid field found for struct github.com...../models.QuestionResponse's field TestQuestions: define a valid foreign key for relations or implement the Valuer/Scanner interface"。有什么解决办法吗?

英文:

let's say I have these 3 struct

type Question struct {
    gorm.Model
    Id            *uint64        `json:"id" gorm:"column=id;primaryKey;autoIncrement"`
	Name          string         `json:"name" gorm:"unique"`
	SkillId       *uint64        `json:"skill_id"`
	TestQuestions []TestQuestion `json:"test_questions"`

}
type Skill struct {
   	gorm.Model
	SkillName     string `json:"skill_name"`
	Question []Question
}
type TestQuestion struct {
    gorm.Model
	QuestionId uint64 `json:"question_id"`
	TestId     uint64 `json:"test_id"`
}

I want to select all questions and for each question i want to select the skill name for that question instead of skill id and i want to preload the TestQuestion
i tried to make this struct to store my result

type struct QuestionResponse(
	SkillName    string
	Name         string    `json:"name"`
	TestQuestions TestQuestion `json:"test_questions"`
}

i tried this query

db.Table("questions").Preload("TestQuestions").
				Joins("inner join skills on questions.skill_id = skills.id").
		Select("questions.name,skills.skill_name, questions.difficulty, questions.max_points, questions.type, questions.expected_time, questions.question_text,questions.file_read_me").
		Find(&question)

but i get this error "invalid field found for struct github.com...../models.QuestionResponse's field TestQuestions: define a valid foreign key for relations or implement the Valuer/Scanner interface"
any solution ?

答案1

得分: 0

首先,我建议你在你的结构体中使用gorm标签,其次,gorm.Model已经为我们提供了一些基本字段,比如ID作为主键等(https://gorm.io/docs/models.html#gorm-Model)。

但是这里是一个结构体,可以节省一些时间:

// gorm.Model定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

我不太明白你想要在你的结构体中做什么,所以我建议你看一下这个链接:https://stackoverflow.com/questions/67588796/gorm-relationship-error-need-to-define-a-valid-foreign-key-for-relations-or-it,并且更多地考虑你的数据库关系。

基本上(感谢https://stackoverflow.com/users/415628/ezequiel-muns):

  • foreignKey应该命名为连接到外部实体的模型本地键字段。
  • references应该命名为外部实体的主键或唯一键。

请记住,.Preload("some stuff")将基本上执行一个select(*),以满足你的结构体的结构(例如,从用户中选择订单)在你的数据库中,所以有时最好在嵌入中拥有你想要的字段,并为该选择拥有一个唯一的结构体,而不是一个“适用于所有”的结构体。

Gorm有一些函数,比如Omit(),可以在插入或更新中省略一个字段。

英文:

First i suggest you use the gorm tags in your struct, and second gorm.Model already give us some basic fields, like ID as primary key, etc (https://gorm.io/docs/models.html#gorm-Model)
But here is the struct to save some time :

// gorm.Model definition
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

I didn't understand what you want to do with your structs, so i recommend you give a look at this: https://stackoverflow.com/questions/67588796/gorm-relationship-error-need-to-define-a-valid-foreign-key-for-relations-or-it , and think more about the relations of your database.

Basic: (thanks to https://stackoverflow.com/users/415628/ezequiel-muns )

  • foreignKey should name the model-local key field that joins to the foreign entity.
  • references should name the foreign entity's primary or unique key.

Keep in mind that .Preload("some stuff"), will basic do a select (*), to satisfy the Struct of your struct (eg. Orders from Users) in your database, so sometimes is just better to have the field you want in the embed and have a unique struct for that select, than a "fits all" struct.
Gorm have some funcs like Omit() to omit a field in a insert or update.

huangapple
  • 本文由 发表于 2021年8月3日 05:52:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/68628299.html
匿名

发表评论

匿名网友

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

确定