Summary
Tried to implement DUPLICATE: Bidirectional many2many relationship solution. After appending different users to the "Followings" and "Followers" fields, any user added to the Following field is also being added to Followers field, and vice versa.
The same happens with BlockedBy and Blocking fields.
I defined User Following and Blockingstruct types as follows
type User struct {
Email string `gorm:"size:100;not null;unique" json:"email"`
...
UserId string `gorm:"primary_key;not null" json:"userid"`
}
type Following struct {
ID string `gorm:"primary_key" json:"id"`
User User `gorm:"foreignKey:ID;references:UserId"`
Followings []*User `gorm:"many2many:user_relation;foreignKey:ID;joinForeignKey:UserA;references:UserId;joinReferences:UserB;constraint:OnDelete:CASCADE"`
Followers []*User `gorm:"many2many:user_relation;foreignKey:ID;joinForeignKey:UserB;references:UserId;joinReferences:UserA;constraint:OnDelete:CASCADE"`
}
type Blocking struct {
ID string `gorm:"primary_key" json:"id"`
User User `gorm:"foreignKey:ID"`
BlockedBy []*User `gorm:"many2many:user_blocks;foreignKey:ID;joinForeignKey:UserIdBlocked;joinReferences:UserId;constraint:OnDelete:CASCADE"`
Blocking []*User `gorm:"many2many:user_blocks;foreignKey:ID;joinForeignKey:UserId;joinReferences:userIdBlocked;constraint:OnDelete:CASCADE"`
}
Loading method
Here's how I first initialized and load some data for testing purposes: // Load autogenerates the tables and records
func Load() {
db, err := database.Connect()
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Creates table for each model
err = db.Debug().DropTableIfExists(
&models.User{},
&models.Following{},
&models.Blocking{},
).Error
if err != nil {
log.Fatal(err)
}
//ERROR while using Postgres on Post model
err = db.Debug().AutoMigrate(
&models.User{},
&models.Following{},
&models.Blocking{},
).Error
if err != nil {
log.Fatal(err)
}
for i, _ := range users {
err = db.Debug().Model(&models.User{}).Create(&users[i]).Error
if err != nil {
log.Fatal(err)
}
userfollowings[i].ID = users[i].UserId
blocked_users[i].ID = users[i].UserId
err = db.Debug().Model(&models.Following{}).Create(&userfollowings[i]).Error
if err != nil {
log.Fatal(err)
}
blocked_users[i].ID = users[i].UserId
err = db.Debug().Model(&models.Blocking{}).Create(&blocked_users[i]).Error
if err != nil {
log.Fatal(err)
}
err = db.Debug().Model(&userfollowings[i]).Related(&userfollowings[i].User, "user_id").Error
if err != nil {
log.Fatal(err)
}
err = db.Debug().Model(&blocked_users[i]).Related(&blocked_users[i].User, "user_id").Error
if err != nil {
log.Fatal(err)
}
if i == 0 {
err = db.Model(&userfollowings[i]).Association("Followings").Append(&users[1], &users[2]).Error
if err != nil {
log.Fatal(err)
}
} else if i == 1 {
err = db.Model(&userfollowings[i]).Association("Followings").Append(&users[2]).Error
if err != nil {
log.Fatal(err)
}
} else if i == 2 {
err = db.Model(&userfollowings[i]).Association("Followings").Append(&users[3]).Error
if err != nil {
log.Fatal(err)
}
} else if i == 3 {
err = db.Model(&userfollowings[i]).Association("Followings").Append(&users[0]).Error
if err != nil {
log.Fatal(err)
}
fo_info := models.Following{}
if err != nil {
log.Fatal(err)
}
console.Pretty(&fo_info)
}
}
}
Displaying Following model query result for UserId: 4
[2021-12-27 12:17:03] [0.90ms] SELECT * FROM `users` INNER JOIN `user_relation` ON `user_relation`.`user_user_id` = `users`.`user_id` WHERE (`user_relation`.`following_id` IN ('4'))
[0 rows affected or returned ]
{
"id": "4",
"User": {
"email": "q4@gmail.com",
"id": "4",
"displayName": "John Lennon",
},
"Followings": [
{
"email": "q@gmail.com",
...,
"userid": "1",
"displayName": "Ringo Starr",
},
],
"Followers": [
{
"email": "q@gmail.com",
...
"userid": "1",
"displayName": "Ringo Starr",
}
]
}
Expected result
[2021-12-27 12:17:03] [0.90ms] SELECT * FROM `users` INNER JOIN `user_relation` ON `user_relation`.`user_user_id` = `users`.`user_id` WHERE (`user_relation`.`following_id` IN ('4'))
[0 rows affected or returned ]
{
"id": "4",
"User": {
"email": "q4@gmail.com",
"id": "4",
"displayName": "John Lennon",
},
"Followings": [
{
"email": "q@gmail.com",
...,
"userid": "1",
"displayName": "Ringo Starr",
},
],
"Followers": [
{
"email": "q2@gmail.com",
...
"userid": "2",
"displayName": "George Harrison",
}
]
}
Since last Friday, I'm unable to make this working out. Tried different resource from Golang Gorm documentation and searched similar SOF Q&A, which didn't provide me any solution or guidance.