Join usage

  • Join(string,interface{},string)

The first param is join type, you can use any keyword of your database type, the second could accept two forms. One is the table’s name as a string type, another is []string{"tablename", "alias"} which size is two. The third is join condition.

Below we will show the usage by example:

Suppose we have two tables, one is user, another is group and every user only belong to one group. So we can define the structs.

type Group struct {
	Id int64
	Name string
}
type User struct {
	Id int64
	Name string
	GroupId int64 `xorm:"index"`
}

If we want to query all user and his’s grpu name. how to do via xorm? The code is below:

type UserGroup struct {
    User `xorm:"extends"`
    Name string
}

func (UserGroup) TableName() string {
	return "user"
}

var users []UserGroup
err := engine.Join("INNER", "group", "group.id = user.group_id").Find(&users)

Here we composite User and string type as a new struct UserGroup. And we add a xorm tag extends on User. Of course, we can also use Sql function to query the data.

var users []UserGroup
err := engine.Sql("select user.*, group.name from user, group where user.group_id = group.id").Find(&users)

And then we find we also need Group’s id because we will put a link on the web page. So we can change the UserGroup, now we composite two struct as a new struct. The code is below:

type UserGroup struct {
    User `xorm:"extends"`
    Group `xorm:"extends"`
}

func (UserGroup) TableName() string {
	return "user"
}

var users []UserGroup
err := engine.Join("INNER", "group", "group.id = user.group_id").Find(&users)

Notice the sequence of composite of User and Group because User has Id and Grpup has Id two. There is a rule we should obey:

The sequence of struct field SHOULD be the same as the sequence of select columns.

And another point should be noticed that if you use the composited struct on html template files. You maybe have to use {{.User.Id}} or {{.Group.Id}} but not {{.Id}}

And for more join tables it also ok.

type Type struct {
	Id int64
	Name string
}

type UserGroupType struct {
    User `xorm:"extends"`
    Group `xorm:"extends"`
    Type `xorm:"extends"`
}

var users []UserGroupType
engine.Table("user").Join("INNER", "group", "group.id = user.group_id").
	Join("INNER", "type", "type.id = user.type_id").
	Find(&users)

Of course , we could use Where, And, Or as condition, or use the second param of Find as condition.

engine.Table("user").Join("INNER", "group", "group.id = user.group_id").
	Join("INNER", "type", "type.id = user.type_id").
	Where("user.name like ?", "%"+name+"%").Find(&users, &User{Name:name})

Finally, we can use alias on the process. For example:

engine.Table("user").Alias("u").
	Join("INNER", []string{"group", "g"}, "g.id = u.group_id").
	Join("INNER", "type", "type.id = u.type_id").
	Where("u.name like ?", "%"+name+"%").Find(&users, &User{Name:name})