Reputation: 133
Using Go 1.10, and CockroachDB via the Postgres pq
driver.
I have a GORM model that looks like this:
type User struct {
ID string `gorm:"type:UUID;primary_key;NOT_NULL"`
UserName string
... <other misc things here>
EnclosedUsers []User `gorm:"many2many:enclosed_user;jointable_foreignkey:parent_id;association_jointable_foreignkey:child_id"`
}
where ecnlosed_user
is (specifically defined because reasons :) )
type EnclosedUsers struct {
ParentID string `gorm:"type:UUID;default:'00000000-0000-0000-0000-000000000000'"`
ChildID string `gorm:"type:UUID;default:'00000000-0000-0000-0000-000000000000'"`
}
That is, each user can have 0 or many enclosed users, and each user may have many parent users. Im trying to preload
all of the enclosed users for each user, however GORM only preloads the first level.
i.e.:
usr1
|-> usr 2
| |->usr3
|
|-> usr4
|->usr6
usr5
|->usr7
The only users that are loaded are usr1, usr2, usr4, usr5, and usr7. usr3 or usr 6 aren't. Im currently trying to recursively force the enclosed users to load with an AfterFind
callback:
func (u *User) AfterFind(scope *gorm.Scope, role *CRRole) error {
var childUsers []User
if err := scope.DB().Model(&u).Related(&childUsers, "EnclosedUsers").Error; err != nil {
return err
}
role.EnclosedRoles = childRoles
return nil
}
However this generates the following SQL:
SELECT "users".* FROM "users" INNER JOIN "enclosed_users" ON "enclosed_users"."child_id" = "enclosed_users"."id" WHERE (user_name = 'test user 1') AND ("enclosed_users"."parent_id" IN ('<UUID HERE>'))
if the user_name = ...
wasn't there, the query would work perfectly.
Any ideas would be greatly appreciated.
Upvotes: 3
Views: 2200
Reputation: 3168
I used this approach https://github.com/go-gorm/gorm/issues/4027 and worked for me perfect.
copy paste from example:
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)
}
Upvotes: 0