英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论