beego orm many to many query

Keywords: Go JSON Google

First, correct the documentation of beego

rel_table
Set the name of the automatically generated m2m relation table

rel_through
If you want to use a custom m2m relationship table in an m2m relationship
Set its name in the format of pkg.path.ModelName through this
eg: app.models.PostTagRel
PostTagRel table needs to have a relationship to Post and Tag

In fact, the format of rel'through is not pkg.path.ModelName. The correct posture is:

// Don't copy. It's just how to use eg
learnBeego/myApp/models.RoleUser

I got stuck here for a day, and then I found the problem with the help of google. There are too few things bd can search for about go

For instance

Requirements: users, roles.
We want to realize that a user can have multiple roles and a role can have multiple users

Data sheet design

user table

id username passwrod created_at updated_at
1 testa 123456 2018-01-01 12:36:47 2018-01-01 12:36:47
2 testb 654321 2018-01-01 12:36:47 2018-01-01 12:36:47

role table

id name created_at updated_at
1 Test role A 2018-01-01 12:36:47 2018-01-01 12:36:47
2 Test role B 2018-01-01 12:36:47 2018-01-01 12:36:47

Role user relationship table

id user_id role_id created_at updated_at
1 1 1 2018-01-01 12:36:47 2018-01-01 12:36:47
2 1 2 2018-01-01 12:36:47 2018-01-01 12:36:47
3 2 1 2018-01-01 12:36:47 2018-01-01 12:36:47

Model

User model

Be careful! When many to many is used, it needs to be done manually to get the relation fields. orm will not automatically complete these query operations for you. Don't think that setting rel_through is complete!

type User struct {
    Id    int64
    Username    string    `orm:"size(128);unique" valid:"Required"`
    password    string    `orm:"size(128);" json:"-" valid:"Required"`
    CreatedAt    time.Time    `orm:"auto_now_add;type(datetime)"`
    UpdatedAt    time.Time    `orm:"auto_now;type(datetime)"`
    Roles    []*Role    `orm:"rel(m2m);rel_through(learnBeego/myApp/models.RoleUser)"`
}

func init() {
    orm.RegisterModel(new(User))
}

func (m *User) TableName() string {
    return "user"
}

// Get user information and user role through user ID
func GetUserById(id int64) (v *User, err error) {
    o := orm.NewOrm()
    v = &User{Id: id}
    if err = o.QueryTable(new(User)).Filter("Id",id).RelatedSel().One(v); err == nil {
        // To get the relation field, o.LoadRelated(v, "Roles") is the key
        // Find the role the user belongs to
        if _, err = o.LoadRelated(v, "Roles");err!=nil{
            return nil, err
        }
        return v, nil
    }
    return nil, err
}

Role model

type Role struct {
    Id    int64
    Name    string
    CreatedAt    time.Time    `orm:"auto_now_add;type(datetime)"`
    UpdatedAt    time.Time    `orm:"auto_now;type(datetime)"`
    Users    []*User    `orm:"reverse(many)"`
}

func init() {
    orm.RegisterModel(new(Role))
}

func (m *Role) TableName() string {
    return "role"
}

User role relationship model

type RoleUser struct {
    Id    int64
    User    *User    `orm:"rel(fk)"`
    Role    *Role    `orm:"rel(fk)"`
    CreatedAt    time.Time    `orm:"type(datetime)"`
    UpdatedAt    time.Time    `orm:"type(datetime)"`
}

func init() {
    orm.RegisterModel(new(RoleUser))
}

func (m *RoleUser) TableName() string {
    return "role_user"
}

Finally in the controller

...

func (c *UserController) GetOne() {
    idStr := c.Ctx.Input.Param(":id")
    id, _ := strconv.ParseInt(idStr, 0, 64)
    v, err := models.GetUserById(id)
    if err != nil {
        c.Data["json"] = "No matching data found"
    } else {
        c.Data["json"] = v
    }
    c.ServeJSON()
}

...

Finally, test

If the URL corresponding to GetOne() is localhost:8080/v1/user/:id
Data returned when http://localhost"8080/v1/user/1 is requested

{
    "Id": 1,
    "Username": "testa",
    "CreatedAt": "2018-01-01T12:36:47+08:00",
    "UpdatedAt": "2018-01-01T12:36:47+08:00",
    "Roles":[
        {
            "Id": 1,
            "Name": "Test roles A",
            "CreatedAt": "2018-01-01T12:36:47+08:00",
            "UpdatedAt": "2018-01-01T12:36:47+08:00",
        },
        {
            "Id": 2,
            "Name": "Test roles B",
            "CreatedAt": "2018-01-01T12:36:47+08:00",
            "UpdatedAt": "2018-01-01T12:36:47+08:00",
        },
    ]
}

Posted by iii on Sat, 30 Nov 2019 20:18:16 -0800