关联查询
多表数据联查时可以用连接,但是数据量大时连接效率不高,GoFrame中提供了模型关联查询,可以简化一些多表联查操作。
以dept
、emp
、hobby
三个表为例,每个部门可以有多个员工,每个员工只有一个部门,每个员工对应一条爱好。
查询所有员工,并关联查询出其所在部门
- 修改
entity.Emp
,加入关联信息
internal/model/entity/emp.go
type Emp struct {
Id uint `json:"id" ` // ID
DeptId uint `json:"dept_id" ` // 所属部门
Name string `json:"name" ` // 姓名
Gender int `json:"gender" ` // 性别: 0=男 1=女
Phone string `json:"phone" ` // 联系电话
Email string `json:"email" ` // 邮箱
Avatar string `json:"avatar" ` // 照片
Dept *Dept `orm:"with:id=dept_id" json:"dept"`
}
- 使用
With
指定关联模型查询
var emps []*entity.Emp
err = dao.Emp.Ctx(ctx).With(entity.Dept{}).Scan(&emps)
不用With
指定关联的话,查询出的结果中Dept
为nil
查询所有员工,并关联查询出部门与爱好
- 修改
entity.Emp
,加入关联信息
internal/model/entity/emp.go
type Emp struct {
Id uint `json:"id" ` // ID
DeptId uint `json:"dept_id" ` // 所属部门
Name string `json:"name" ` // 姓名
Gender int `json:"gender" ` // 性别: 0=男 1=女
Phone string `json:"phone" ` // 联系电话
Email string `json:"email" ` // 邮箱
Avatar string `json:"avatar" ` // 照片
Dept *Dept `orm:"with:id=dept_id" json:"dept"`
Hobby *Hobby `orm:"with:emp_id=id" json:"hobby"`
}
- 使用
With
指定需要关联的内容
var emps []*entity.Emp
err = dao.Emp.Ctx(ctx).With(entity.Dept{}, entity.Hobby{}).Where("dept_id", 101).Scan(&emps)
也可以用WithAll
关联所有
var emps []*entity.Emp
err = dao.Emp.Ctx(ctx).WithAll().Where("dept_id", 101).Scan(&emps)
查询部门,关联查询出每个部门的员工
- 修改
entity.Dept
,加入关联信息
internal/model/entity/dept.go
// Dept is the golang structure for table dept.
type Dept struct {
Id uint `json:"id" ` // ID
Pid uint `json:"pid" ` // 上级部门ID
Name string `json:"name" ` // 部门名称
Leader string `json:"leader" ` // 部门领导
Phone string `json:"phone" ` // 联系电话
Emps []*Emp `orm:"with:dept_id=id" json:"emps"`
}
- 查询
var depts []*entity.Dept
err = dao.Dept.Ctx(ctx).With(entity.Emp{}).Scan(&depts)
上述关联查询直接在实体类里面修改,但实体类里的内容是用工具自动生成的,一般情况下不要修改。所以在进行关联查询时,需要重新自定义结构体,只需要保留需要查询的字段即可(用于关联的字段必须存在)
type MyDept struct {
g.Meta `orm:"table:dept"`
Id uint `json:"id" ` // ID
Name string `json:"name" ` // 部门名称
Leader string `json:"leader" ` // 部门领导
Phone string `json:"phone" ` // 联系电话
}
type MyEmp struct {
g.Meta `orm:"table:emp"`
Id uint `json:"id" ` // ID
DeptId uint `json:"dept_id" ` // 所属部门
Name string `json:"name" ` // 姓名
Phone string `json:"phone" ` // 联系电话
Dept *MyDept `orm:"with:id=dept_id" json:"dept"`
}
var emps []*MyEmp
err = dao.Emp.Ctx(ctx).With(MyDept{}).Scan(&emps)
自定义结构体时,需要用g.Meta
及orm
标签指定对应的数据表