Your Question
I want to select specific fields of User, so I defined a smaller struct called APIUser which can select specific fields automatically. Also I want preload Orders when find users.
type User struct {
gorm.Model
Name string
Age int
Gender string
Orders []Order
}
type Order struct {
gorm.Model
UserID uint
Price float64
}
type APIUser struct {
ID uint
Name string
Orders []Order
}
db.Model(&User{}).Preload("Orders").Find(&APIUser{})
When I run the above code, I get the following error.
[error] invalid field found for struct main.APIUser's field Orders, need to define a valid foreign key for relations or it need to implement the Valuer/Scanner interface
panic: reflect: call of reflect.Value.Field on uint Value
Is it impossible to use it this way?
The document you expected this should be explained
Expected answer
Comment From: jinzhu
db.Model(&User{}).Preload("Orders", func(tx gorm.DB) gorm.DB { return tx.Select("Name") }).Find(&APIUser{})
Comment From: wolfapple
@jinzhu
My question was not whether I can select fields when calling the Preload function, but how to use Preload on smaller struct for smart select fields.
After this and that experiment, the following results were obtained.
type User struct {
gorm.Model
Name string
Age int
Gender string
Orders []Order
}
type Order struct {
gorm.Model
UserID uint
Price float64
}
type APIUser struct {
ID uint
Name string
Orders []Order `gorm:"foreignKey:UserID"`
}
db.Model(&User{}).Preload("Orders").Find(&APIUser{}) // panic!
db.Table("users").Preload("Orders").Find(&APIUser{}) // it works, but smart select is not working!
Instead of using the Model function, I found that specifying the table name works. But smart select didn't work. I have confirmed that the following query is executed.
SELECT * FROM `orders` WHERE `orders`.`user_id` = 1 AND `orders`.`deleted_at` IS NULL
SELECT * FROM `users`
Since the APIUser structure only has an ID and a Name, the following query should be executed.
SELECT `users`.`id`,`users`.`name` FROM `users` WHERE `users`.`deleted_at` IS NULL
Comment From: vuhoanglam
I ran into the same problem, I think this is a bug
Comment From: therealpaulgg
I can confirm I have the exact same problem, panic and everything. Smart select works on anything that does not have associations, but if I try to preload and do associations there is a panic. This issue should be re-opened.
Comment From: fnsne
I met this problem too. When I using with the smart select field(like struct APIUser other mention above), I will panic. But when using with the model struct( like struct User above) the preload works well.
Comment From: fnsne
I think there is something not defined. Because when I change to using embedded, it works well.
I only change the APIUser to this.
type APIUser struct {
gorm.Model
Name string
Orders []Order `gorm:"foreignKey:ID"`
}
And the preload words well.
db.Preload("Orders").Model(&User{}).Find(&APIUser{})
Comment From: wolfapple
@fnsne Have you tried testing even when data actually exists in the users table and the orders table? When there is no data, the panic does not occur as you said, but if there is data, it still panics.
Comment From: fnsne
@wolfapple
I don't know how to execute the Find(&APIUser{}) with no data in the two tables.
But I used the command above I wrote, it works with data in two tables.
There is no panic.
Maybe the version I'm using? I use v1.20.7.
Comment From: loeffel-io
This is amazing @jinzhu
db.Model(&User{}).Preload("Orders", func(tx *gorm.DB) *gorm.DB {
return tx.Select("Name")
}).Find(&APIUser{})
But how to do that with Joins?