Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Many-to-Many and attributes #719

Closed
Quentin-M opened this issue Nov 10, 2015 · 4 comments
Closed

Many-to-Many and attributes #719

Quentin-M opened this issue Nov 10, 2015 · 4 comments

Comments

@Quentin-M
Copy link

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.

@jinzhu
Copy link
Member

jinzhu commented Jan 3, 2016

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: "1@1.com",
        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)
}

@rbatukaev
Copy link

@jinzhu How do I append and delete items in such relationships?

@jinzhu
Copy link
Member

jinzhu commented Feb 17, 2016

@rbatukaev User, GroupUser are normal has many relations, refer https://github.com/jinzhu/gorm#association-mode

@acidjazz
Copy link

acidjazz commented Dec 1, 2022

This needs to be in the documentation - and proper pivot support needs to be added

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants