Hi !
I was wondering what would be the best way to create a many-to-many relationship with extra attributes ? For instance, I'd like to have Library <--> LibraryHasBook (count) <--> Books
. LibraryHasBook would have the following fields (library_id, book_id, count)
. Has anyone done or seen that pattern before ?
I was thinking of:
type Library struct {
ID uint `gorm:"primary_key"`
Name string
Books []LibraryHasBook
}
type LibraryHasBook struct {
Library Library `gorm:"primary_key"`
Book Book `gorm:"primary_key"`
Count uint
}
type Book struct {
ID uint `gorm:"primary_key"`
Name string
Libraries []LibraryHasBook
}
And then inserting a new Book & associated Libraries with something like:
book := Book{
Name: "The Lords of the Ring",
Libraries: []LibraryHasBook {
LibraryHasBook{
Library: Library{Name: "Tolkien Specialists"},
Count: 10,
},
LibraryHasBook{
Library: Library{Name: "Awesome Library"},
Count: 3,
},
},
}
db.Create(&book)
But I am quite not sure if it would work (the Go is most likely not valid anyways as I typed it directly in that issue), especially if GORM would be able to fill LibraryHasBook's Library, and what annotation should be used, etc. Should I instead use a transaction, create Libraries, create Book, then LibraryHasBooks, specifying explictely the book/librairies and commit, would it work better ?
How would it be possible then to get a book with its Libraries and count ?
I did not find anything related in the docs, pardon me if I am blind.
Thank you so much.
Hi @Quentin-M
yes, it is possible to do this, refer below example
package main
import (
"github.com/davecgh/go-spew/spew"
_ "github.com/lib/pq"
"github.com/jinzhu/gorm"
)
type User struct {
ID int
Email string
GroupUsers []*GroupUser
}
type Group struct {
ID int
Name string
GroupUsers []*GroupUser
}
type GroupUser struct {
ID int
Group *Group
GroupID int
User *User
UserID int
Owner bool
}
func (*GroupUser) TableName() string {
return "group_user"
}
func main() {
db, err := gorm.Open("postgres", "user=gorm DB.name=gorm sslmode=disable")
if err != nil {
panic(err)
}
db.AutoMigrate(&User{}, &Group{}, &GroupUser{})
db.LogMode(true)
db.Debug().Save(&User{
Email: "[email protected]",
GroupUsers: []*GroupUser{
{
Group: &Group{
Name: "ccc",
},
Owner: true,
},
},
})
var group Group
if err := db.Preload("GroupUsers.User").First(&group).Error; err != nil {
panic(err)
}
spew.Dump(group)
}
@jinzhu How do I append and delete items in such relationships?
@rbatukaev User
, GroupUser
are normal has many relations, refer https://github.com/jinzhu/gorm#association-mode
Most helpful comment
Hi @Quentin-M
yes, it is possible to do this, refer below example