Gorm: Proper way to declare a recursive one to many or belongsTo relationship

Created on 14 Jun 2018  路  6Comments  路  Source: go-gorm/gorm

What version of Go are you using (go version)?

Go 1.10

Which database and its version are you using?

Postgres

Please provide a complete runnable program to reproduce your issue. IMPORTANT

Hello, I have been trying to make in the proper way the self-relationship, it's about a menu item that can have many sub-items, so, first: is better to track who is the parent or to know who are the children? second: I wasn't able to make it works, I tried:

type MenuItem struct{
    ID        uint `gorm:"primary_key"`
    Name string `gorm:"unique;not null"`
    Text string
    Parent *MenuItem `gorm:"association_foreignkey:Refer"`
    ParentId int `gorm:"TYPE:integer REFERENCES menuitems"`
}

But, in this case when I try to insert I get the error: (pq: insert or update on table "menuitems" violates foreign key constraint "menuitems_parent_id_fkey")
Also tried:

type MenuItem struct{
    ID        uint `gorm:"primary_key"`
    Name string `gorm:"unique;not null"`
    Text string
    Parent MenuItem `gorm:"association_foreignkey:ID"`
}

And, here I get: invalid recursive type MenuItem

Thank you and I appreciate any help!

Most helpful comment

@gstvg thank you! I managed by doing:

type MenuItem struct {
    ID       uint   `gorm:"primary_key"`
    Name     string `gorm:"unique;not null"`
    Text     string
    Parent   *MenuItem `gorm:"foreignkey:ParentID"`
    ParentID uint
}

And then I was able to load the related menu-item (parent) by doing:

db.Model(&menu).Related(&menu, "ParentID")

All 6 comments

Depending on the code, may the children is being inserted first with an invalid fk to its ,at the time, un-inserted parent?

Qor Example achieves that in that way:
https://github.com/qor/qor-example/blob/ce0ab4ecdd6a2fa811e1aee4ecdeffbd8f343f08/models/products/category.go

@gstvg ok, I get it. Well, when a child is inserted they could select a parent (is not strictly required), but in that case that item would be a parent (I mean, in the first level of the hierarchy). Then, I think that I have to track is who is the parent instead saving children?

Depending your use case, yes, could be better to track who is the parent cause then you would have the full hierarchy on a single object, making it easier to use in templates or encoding to json,xml...

@gstvg oko, in that case I implemented the relation as:

type MenuItem struct{
    ID        uint `gorm:"primary_key"`
    Name string `gorm:"unique;not null"`
    Text string
    Parent MenuItem `gorm:"association_foreignkey:ID"`
}

But, I am getting the error: invalid recursive type MenuItem
so, what am I missing?

this code need to have Parent as a pointer to MenuItem:
Parent *MenuItemgorm:"association_foreignkey:ID"``

But i would write that way:

type MenuItem struct {
    ID        uint `gorm:"primary_key"`

    Name string `gorm:"unique;not null"`
    Text string
    Childs []MenuItem

        MenuItemID //parent id, would be 0 for top-level menu
}

@gstvg thank you! I managed by doing:

type MenuItem struct {
    ID       uint   `gorm:"primary_key"`
    Name     string `gorm:"unique;not null"`
    Text     string
    Parent   *MenuItem `gorm:"foreignkey:ParentID"`
    ParentID uint
}

And then I was able to load the related menu-item (parent) by doing:

db.Model(&menu).Related(&menu, "ParentID")

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alanyuen picture alanyuen  路  3Comments

izouxv picture izouxv  路  3Comments

fieryorc picture fieryorc  路  3Comments

pjebs picture pjebs  路  3Comments

corvinusy picture corvinusy  路  3Comments