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)
}