Your Question
Sorry if this is documented somewhere and I missed it, new to gorm/go in general :).
If I have the following structure:
type Person struct {
gorm.Model
Name string `json:"name"`
ParentID *uint `gorm:"type:uuid" json:"parent_id"`
FamilyID *uint `gorm:"type:uuid" json:"family_id"`
Children []Person `gorm:"foreignKey:ParentID" json:"children"`
}
type Family struct {
gorm.Model
Name string `gorm:"not null" json:"name"`
People []Person
}
How would I go about preloading ALL People, Children, and any nested grandchildren, etc etc... when querying for a Family object?
The document you expected this should be explained
https://gorm.io/docs/has_many.html#Self-Referential-Has-Many https://gorm.io/docs/preload.html
Looking through the docs, I've found the sections of declaring self referencing has many fields, preloading all with clause.Associations, and nested preloading with db.Preload("People.Children")
When doing something like
db.Preload("People.Children").Preload(clause.Associations).Find(&Family)
I'm able to return people -> children but then any further grandchildren, children of grandchildren aren't preloaded/returned. This also requires knowing exactly how many nested levels of children there could be, which I feel like is the incorrect approach to this problem?
Expected answer
I'm essentially looking for an object that would look something like this: (people have children and their children can have children. could essentially be multiple tiers of nested children?)
{
"name": "Family Name",
"People": [
{
"ID": 1,
"name": "John",
"parent_id": null,
"children": [
{
"ID": 2,
"name": "Steve",
"parent_id": 1,
"children": [
{
"ID": 4,
"name": "Andrew",
"parent_id": 2,
"children": null
}
]
},
{
"ID": 3,
"name": "Mary",
"parent_id": 1,
"children": null
}
]
}
]
}
Am I even approaching this problem correctly here lmao? Thanks in advance for any pointers in the right direction!
Comment From: jinzhu
db.Preload("Person.Children").Find(&family)
if there are many other associations, you could use clause.Associations, it will preload all first level associations, to preload the next level, use it like "Person." + clause.Associations, for example:
db.Preload(clause.Associations).Preload("Person." + clause.Associations).Find(&family)
Comment From: birdycn
it can not preload all chilren,only once
Comment From: CSNight
it can not preload all chilren,only once
you can try this
type Menu struct{
Id int `json:"id" gorm:"primaryKey;type:int"`
Pid int `json:"pid" gorm:"primaryKey;type:int"`
Children []Menu `json:"children" gorm:"foreignKey:pid"`
}
func GetMenusTree() ([]Menu, error) {
var views []Menu
err := db.Model(&Menu{}).Where("pid = ?", 0).Preload(clause.Associations, preload).Find(&views).Error
if err != nil {
return nil, err
}
return views, nil
}
func preload(d *gorm.DB) *gorm.DB {
return d.Preload("Children", preload)
}