package pg_test import ( "fmt" "github.com/go-pg/pg" "github.com/go-pg/pg/orm" ) func init() { // Register many to many model so ORM can better recognize m2m relation. // This should be done before dependant models are used. orm.RegisterTable((*ElemToElem)(nil)) } type Elem struct { Id int Elems []Elem `pg:"many2many:elem_to_elems,joinFK:sub_id"` } type ElemToElem struct { ElemId int SubId int } func createManyToManySefTables(db *pg.DB) error { models := []interface{}{ (*Elem)(nil), (*ElemToElem)(nil), } for _, model := range models { err := db.CreateTable(model, &orm.CreateTableOptions{ Temp: true, }) if err != nil { return err } } return nil } func ExampleDB_Model_manyToManySelf() { db := connect() defer db.Close() if err := createManyToManySefTables(db); err != nil { panic(err) } values := []interface{}{ &Elem{Id: 1}, &Elem{Id: 2}, &Elem{Id: 3}, &ElemToElem{ElemId: 1, SubId: 2}, &ElemToElem{ElemId: 1, SubId: 3}, } for _, v := range values { err := db.Insert(v) if err != nil { panic(err) } } // Select elem and all subelems with following queries: // // SELECT "elem"."id" FROM "elems" AS "elem" ORDER BY "elem"."id" LIMIT 1 // // SELECT elem_to_elems.*, "elem"."id" FROM "elems" AS "elem" // JOIN elem_to_elems AS elem_to_elems ON (elem_to_elems."elem_id") IN (1) // WHERE ("elem"."id" = elem_to_elems."sub_id") elem := new(Elem) err := db.Model(elem).Relation("Elems").First() if err != nil { panic(err) } fmt.Println("Elem", elem.Id) fmt.Println("Subelems", elem.Elems[0].Id, elem.Elems[1].Id) // Output: Elem 1 // Subelems 2 3 }