Foreign key on source struct? - go

I'm starting with Gorm and trying to model the following:
type MyLink struct {
gorm.Model
Title string
Url string
}
// group of links under a single title
type MyLinkSection struct {
gorm.Model
Title string
Links []MyLink
}
type MyPage struct {
gorm.Model
PageUrl MyLink
Artists []MyLinkSection
}
As you can see I want to be able to refer to the same struct, MyLink as both a foreign keyed object from MyPage but also as a one-to-many from MyLinkSection.
It seems I have to declare the foreign key ID in MyLink which would seem to make this not possible.
Is there any way of setting up tables like this? With a normal DB I'd just have a field in MyPage called my_link_id, with something similar for MyLinkSection.

It seems it is possible to specify forward relations:
PageUrl MyLink `gorm:"ForeignKey:PageUrlId"`
PageUrl Id uint

Related

Does GORM support attibutes of many to many relationships?

Using the gorm.io library, how would I implement a many to many relationship, where the relationship itself has attributes?
Example:
Without the attribute I would do it something like this, but I can't find a solution to my Problem in the GORM docs.
type Recipe struct {
gorm.Model
Name string
Ingredients []Ingredient `gorm:"many2many"`
}
type Ingredient struct {
gorm.Model
Name string
}

GORM AutoMigrate Has One & Has Many:

I want to create a model User and Social where the User model has many Socials. Ideally a Social type would also have has one relation to simpilify querying from either side. Here is a code sample:
database type is MySQL 8.0
type base struct {
ID string `json:"id" gorm:"type:char(36);primaryKey;"`
Created time.Time `json:"created" gorm:"autoCreateTime"`
Updated time.Time `json:"updated" gorm:"autoUpdateTime"`
}
type User struct {
base
Friends []*User `json:"friends" gorm:"many2many:friends"`
Socials []*Social `json:"socials"`
}
type Social struct {
base
Provider string `json:"provider" gorm:"type:varchar(32);index"`
Identifier string `json:"identifier" gorm:"type:varchar(32);index"`
User *User `json:"user" gorm:"foreignKey:ID"`
Token string `json:"token"`
Link string `json:"link" gorm:"type:varchar(128)"`
}
Im getting the following error when using db.AutoMigrate(&User{}, &Social{}):
model.Social's field User, need to define a valid foreign key for relations or it need to implement the Valuer/Scanner interface
runtime error: invalid memory address or nil pointer dereference
I have tried:
adding gorm:"foreignKey:ID" to User.Socials tags
not using pointers (eg in User struct Socials []Social instead of Socials []*Social)
but the issue remains
According to documentation (https://gorm.io/docs/has_many.html#Has-Many),
you need to use objects, not references
type User struct {
base
Friends []User `json:"friends" gorm:"many2many:friends"`
Socials []Social `json:"socials"`
}
no * here
Also you can add UserID field to Social
type Social struct {
base
UserID string
Provider string `json:"provider" gorm:"type:varchar(32);index"`
Identifier string `json:"identifier" gorm:"type:varchar(32);index"`
User *User `json:"user" gorm:"foreignKey:ID"`
Token string `json:"token"`
Link string `json:"link" gorm:"type:varchar(128)"`
}
and add
type User struct {
base
FriendOf string `gorm:""`
Friends []*User `json:"friends" gorm:"many2many:friends,foreignKey:FriendOf"`
Socials []*Social `json:"socials"`
}
Issue was here:
type base struct {
...
}
type User {
base
...
}
type Social {
base
...
}
Since I thought base would just be package local definition I messed up the capitalization and had a private primary key.
Another issue was touched on by #vodolaz095, but (imo) not sufficiently clarified for any new go-gorm user.
It does not seem to be possible to use a has one relation like User User be the foreign key for a has many relation like Socials []Social gorm:"foreignKey:User". It is required to be split up as #vodolaz095 displayed in his 2nd code block

Defining Belongs To relation for anonymous field using GORM

I wanted to create relationnal database structure in a using the go package Gorm.
I wanted to add foreign keys to my structure, it works perfectly on regular field, but it does not seem to work when I want to make foreign key for anonymous fields.
Here is some simplified code to demonstrate my case
type StructA struct {
gorm.Model
SimpleFieldID int // appears in database as foreign key
SimpleField StructB
TranslationID int // appears in database as a regular int
Translation
}
type StructB struct {
gorm.Model
SomeField string
SomeOtherField string
}
type Translation struct {
gorm.Model
En string
Fr string
}
I wanted to have anonymous field in the first place to be able to call some GetName() method on any object that has the Translation attribute.
I found this question, but the given anwser was for the has-one relation, where I want to use a belongs-to relation.

Go-Gorm: will the foreignkey be auto-populated when I set an object?

In the documentation we have this example:
type User struct {
gorm.Model
Name string
}
// `Profile` belongs to `User`, `UserID` is the foreign key
type Profile struct {
gorm.Model
UserID int
User User
Name string
}
If I do something like profile.User = &user, will that automatically populate the UserID field? Is it recommended to set both? Like:
profile.User = &user
profile.UserID = &user.ID
Or is that pointless? Furthermore, could I alternatively just set the UserID field and ignore the User field entirely?
If I do something like profile.User = &user, will that automatically populate the UserID field?
Just writing profile.User = &user will not populate the UserID field. Once you add the profile to the database. gorm will automatically populate the foreign key.
Is it recommended to set both?
Nope. In fact, you should not set the UserID yourself. This answers the last question as well.

One-to-many recursive relationship in GORM

I need to have an Organization which have relation to parent one. Something like this:
type Organization struct {
gorm.Model
Parent *Organization `gorm:"ForeignKey:ParentId"`
Name string `gorm:"size:30"`
Description string `gorm:"size:100"`
}
I want to have ParentId field which will be referenced to id field in the same table. But as I see there is no field and relation.
How can I fix it ?
I have solved it like this, but I am not sure that it is a correct way:
type Organization struct {
gorm.Model
Parent *Organization
ParentId int `gorm:"TYPE:integer REFERENCES organizations"`
Name string `gorm:"size:30"`
Description string `gorm:"size:100"`
}

Resources