Beego脱坑(十四)ORM高级查询


title: Beego脱坑(十四)ORM高级查询
tags: go,beego,orm
author : Clown95


本文将讲述beego ORM的一些高级查询,这也是ORM最核心的部分,本文所有的操作都基于下面的student

Beego脱坑(十四)ORM高级查询_第1张图片

Operators

在beego ORM中也有类似于SQL语句中的操作符,欲善其事,必利其器,我们先来了解他们,beego ORM目前支持的操作符为:

操作符 说明 等同Sql操作符
gt greater的缩写,表示大于的意思 >
gte greater than or equal的缩写,即大于等于 >=
lt less than的缩写,表示小于 <
lte less thanor equal的缩写,小于等于 <=
in 等同与sql语言中的in in
exact 等于 =
contains 包含,一般用于字符类型,如包含某某字符 like '%查询内容%'
startswith 以…起始,一般用于字符类型,如从什么字符开始 like '开始字符%'
endswith 以…结束 ,一般用于字符类型,如以什么字符结束 like '%结束字符'
isnull 表示改字段不能为空

在beego中 操作符前面添加 字母 i 表示忽略大小写,如 iexact、icontains 、istartswith 和iendswith 

exact

我们最先演示下exact 它相当于 = ,现在我们需要通过它查询出 stu_id =3 的一条数据。

func (this *OperatorsController) GetExact() {
    orm := orm.NewOrm()
    // 获取表句柄
    stu := Student{}
    qs := orm.QueryTable("student")
    // select * from student where id =3;
    err := qs.Filter("stu_id__exact", 3).One(&stu) // 过滤器
    if err != nil {
        this.Ctx.WriteString(strconv.Itoa(stu.StuId) + " " + stu.Name + " " + stu.Age + " " + stu.Hobby)
    }else{
        this.Ctx.WriteString("查询失败")    
    }
}

Beego脱坑(十四)ORM高级查询_第2张图片

上面的代码相当于sql语句 :

select * from student where id =3;
  • QueryTable("student") : 返回 student表的QuerySeter 对象。ORM 以 QuerySeter 来组织查询,每个返回 QuerySeter 的方法都会获得一个新的 QuerySeter 对象;
  • Filter("stu_id__exact" ,3) : 用来过滤查询结果,起到包含条件的作用,第一个参数是我匹配规则,第二个参数是我们匹配的值 ; 使用如果使用操作符,字段和操作符直接使用两个"_"连接,具体格式为:字段__操作符;
  • One(&stu) : 返回单条记录 ,参数一般是结构体对象。

gte

现在我们来使用 gte 获取 age>=25岁的所有数据, 下面我们看代码。

func (this *OperatorsController) GetAllGte() {
    orm := orm.NewOrm()
    var stus = []*Student{}
    // 获取表句柄
    qs := orm.QueryTable("student")
    // select * from student where age>=25;
    n, err := qs.Filter("age__gte", 20).All(&stus) // 过滤器
    if err == nil && n > 0 {
        for i := 0; i < len(stus); i++ {
            this.Ctx.WriteString(strconv.Itoa(stus[i].StuId) + " " + stus[i].Name + " " + stus[i].Age + " " + stus[i].Hobby + "\n")
        }
    } else {
        this.Ctx.WriteString("查询失败")
    }
}

Beego脱坑(十四)ORM高级查询_第3张图片

上面的代码相当于sql语句:

select * from student where age>=25;
  • All(&stus) : 返回对应的结果集对象。 和One不一样的是,All返回所有符合条件的数据,参数是指针切片( []Type 或者[]*Type ),返回数据cols和error

in

现在我们通过 in 查询 stu_id 为 1、4、5、10的数据集。

func (this *OperatorsController) GetIn() {
    orm := orm.NewOrm()
    var stus = []*Student{}
    // 获取表句柄
    qs := orm.QueryTable("student")
    // select * from student where stu_id in(1,4,5,10);
    n, err := qs.Filter("stu_id__in",1,4,5,10 ).All(&stus) // 过滤器
    if err == nil && n > 0 {
        for i := 0; i < len(stus); i++ {
            this.Ctx.WriteString(strconv.Itoa(stus[i].StuId) + " " + stus[i].Name + " " + stus[i].Age + " " + stus[i].Hobby + "\n")
        }
    } else {
        this.Ctx.WriteString("查询失败")
    }
}

Beego脱坑(十四)ORM高级查询_第4张图片

上面的代码相当于sql语句:

select * from student where stu_id in(1,4,5,10);

contains

接着我们使用 contains 来查询 name中包含 "小" 字的数据集。

func (this *OperatorsController) GetContains() {
    orm := orm.NewOrm()
    var stus = []*Student{}
    // 获取表句柄
    qs := orm.QueryTable("student")
    // select * from student where name like '小%';
    n, err := qs.Filter("name__contains", "小").All(&stus) // 过滤器
    if err == nil && n > 0 {
        for i := 0; i < len(stus); i++ {
            this.Ctx.WriteString(strconv.Itoa(stus[i].StuId) + " " + stus[i].Name + " " + stus[i].Age + " " + stus[i].Hobby + "\n")
        }
    } else {
        this.Ctx.WriteString("查询失败")
    }
}

Beego脱坑(十四)ORM高级查询_第5张图片

上面的代码相当于sql语句:

select * from student where name like '小%';

操作符我们就演示到这里,其他的几个用法都大同小异,大家可以自己拓展。

 

高级查询接口

高级查询接口我们在 Operators 部分里面,使用过 Filter、One、All这三个了。我们就不在重复介绍了,我们主要来了解下其他的接口函数。

方法 说明
Exclude 用来过滤查询结果,起到 排除条件的作用,相当于!Filter
Limit 限制最大返回数据行数
Offset 设置偏移行数
GroupBy 数据分组
OrderBy 数据排序
Distinct 获取不重复的数据
Count 依据当前的查询条件,返回结果行数
Exist 判断查询的数据是否存在
Values 返回结果集数据,存储到map中
ValuesList 顾名思义,返回的结果集以slice存储
PrepareInsert 用于批量插入数据
Delete 依据当前查询条件,进行批量删除操作
Update 依据当前查询条件,进行批量更新操作

Exclude

现在我们来使用Exclude 排除 年龄小于等于25的数据.

func (this * ADvancedApiController) GetExclude(){
    orm := orm.NewOrm()
    var stus = []*Student{}
    // 获取表句柄
    qs := orm.QueryTable("student")
    //select * from student where not age <=25 ;
    n, err := qs.Exclude("age__lte",25).All(&stus)
    if err == nil && n > 0 {
        for i := 0; i < len(stus); i++ {
            this.Ctx.WriteString(strconv.Itoa(stus[i].StuId) + " " + stus[i].Name + " " + stus[i].Age + " " + stus[i].Hobby + "\n")
        }
    } else {
        this.Ctx.WriteString("查询失败")
    }
}

上面的代码相当于sql语句:

select * from student where not age <=25 ;

Beego脱坑(十四)ORM高级查询_第6张图片

Limit

有时候数据过多,我们只想显示部分数据,比如现在我们只需要显示前5个数据

func (this * ADvancedApiController) GetLimit(){
    orm := orm.NewOrm()
    var stus = []*Student{}
    // 获取表句柄
    qs := orm.QueryTable("student")
    //select * from student limit 5 ;
    n, err := qs.Limit(5) .All(&stus)
    if err == nil && n > 0 {
        for i := 0; i < len(stus); i++ {
            this.Ctx.WriteString(strconv.Itoa(stus[i].StuId) + " " + stus[i].Name + " " + stus[i].Age + " " + stus[i].Hobby + "\n")
        }
    } else {
        this.Ctx.WriteString("查询失败")
    }
}

Beego脱坑(十四)ORM高级查询_第7张图片

上面的代码相当于sql语句:

select * from student limit 5 ;

当然我们还可以设置偏移量来设置分页 ,我们来修改Limit,显示6-10的数据:

n, err := qs.Limit(5,5) .All(&stus)

Beego脱坑(十四)ORM高级查询_第8张图片

GroupBy

通过 age 进行分组

func (this * ADvancedApiController) GetGroupBy(){
    orm := orm.NewOrm()
    var stus = []*Student{}
    qs := orm.QueryTable("student")
    n, err := qs.GroupBy("age").All(&stus)
    if err == nil && n > 0 {
        for i := 0; i < len(stus); i++ {
            this.Ctx.WriteString(strconv.Itoa(stus[i].StuId) + " " + stus[i].Name + " " + stus[i].Age + " " + stus[i].Hobby + "\n")
        }
    } else {
        this.Ctx.WriteString("查询失败")
    }
}

OrderBy

通过 age 和 stu_id 进行排序 表达式前面使用 "-" 代表降序排序

func (this * ADvancedApiController) GetOrderBy(){
    orm := orm.NewOrm()
    var stus = []*Student{}
    qs := orm.QueryTable("student")
    n, err := qs.OrderBy("-age","stu_id").All(&stus)
    if err == nil && n > 0 {
        for i := 0; i < len(stus); i++ {
            this.Ctx.WriteString(strconv.Itoa(stus[i].StuId) + " " + stus[i].Name + " " + stus[i].Age + " " + stus[i].Hobby + "\n")
        }
    } else {
        this.Ctx.WriteString("查询失败")
    }
}

Count

使用Count 查询有多少行数据

func (this *ADvancedApiController) GetCount() {
    orm := orm.NewOrm()
    //select count(*) from student;
    n, err := orm.QueryTable("student").Count()
    if err != nil {
        this.Ctx.WriteString("查询出错!\n")
        return
    }else {
        this.Ctx.WriteString("n = " + strconv.Itoa(int(n)))
    }
}

上面的代码相当于sql语句:

select count(*) from student;

Exist

我们用 Exist 判断 stu_id =8 和 stu_id =15 的数据是否存在

func (this *ADvancedApiController) GetExist() {
    orm := orm.NewOrm()
    qs := orm.QueryTable("student")
    flag := qs.Filter("stu_id", 8).Exist()
    if flag {
        this.Ctx.WriteString("stu_id=8 存在\n")
    }else {
        this.Ctx.WriteString("stu_id=8 不存在\n")
    }
    flag = qs.Filter("stu_id", 15).Exist()
    if flag {
        this.Ctx.WriteString("stu_id=15 存在\n")
    }else {
        this.Ctx.WriteString("stu_id=15 不存在\n")
    }
}

Beego脱坑(十四)ORM高级查询_第9张图片

Values

我们还可以 使用Values 返回结果集的 key => value 值 ,key 为Model里的Field name, value的值是interface{}类型,如果你要将value赋值给struct中的某字段,需要根据结构体对应字段类型使用断言获取真实值。

func (this *ADvancedApiController) GetValues() {
    //将每一条记录的字段作为键,数据作为值存入map中,每个map就是一条记录。
    var maps []orm.Params //[map, map, map]
    orm := orm.NewOrm()
    _, err := orm.QueryTable("student").Values(&maps, )
    if err != nil {
        this.Ctx.WriteString("查询出错!")
        return
    }
    for _, m := range maps {
        this.Ctx.WriteString(m["Name"].(string) + " " + m["Age"].(string) + "   " + m["Hobby"].(string) + "\n")
    }
}

Beego脱坑(十四)ORM高级查询_第10张图片

当然我们还可以直接指定 expr 级联返回需要的数据

func (this *ADvancedApiController) GetValuesField() {
    //将每一条记录的字段作为键,数据作为值存入map中,每个map就是一条记录。
    var maps []orm.Params //[map, map, map]
    orm := orm.NewOrm()
    _, err := orm.QueryTable("student").Values(&maps, "Name","Hobby")
    if err != nil {
        this.Ctx.WriteString("查询出错!")
        return
    }
    for _, m := range maps {
        this.Ctx.WriteString(m["Name"].(string) + " " + m["Hobby"].(string) + "\n")
    }
}

ValuesList

顾名思义,返回的结果集以slice存储,结果的排列与 Model 中定义的 Field 顺序一致,返回的每个元素值以 string 保存。

func (this *ADvancedApiController) GetValuesList() {
    var list []orm.ParamsList
    orm := orm.NewOrm()
    _, err := orm.QueryTable("student").ValuesList(&list, "Name", "Age", "Hobby")
    if err != nil {
        this.Ctx.WriteString("查询出错!")
        return
    }
    for _, row := range list {
        for _, col := range row {
            this.Ctx.WriteString(col.(string) + " ")
        }
        this.Ctx.WriteString("\n")
    }
}

 

Beego脱坑(十四)ORM高级查询_第11张图片

PrepareInsert

我们使用PrepareInsert 在添加点数据,并且我们多提交一次数据,方便演示下面的批量删除

func (this *ADvancedApiController) GetPrepareInsert() {

    var stus []*Student
    stu1 := Student{Name:"银之介", Age:"60", Hobby:"辣妹"}
    stu2 := Student{Name:"正男", Age:"5", Hobby:"小爱"}
    stu3 := Student{Name:"阿呆", Age:"6", Hobby:"甩鼻涕"}
    stu4 := Student{Name:"园长", Age:"56", Hobby:"园艺"}
    stus = append(stus, &stu1, &stu2, &stu3, &stu4)
    orm := orm.NewOrm()
// insert into student(name, age.hobby) values("银之介", "60", "辣妹"), (正男", "5", "小爱");
    insert, _ := orm.QueryTable("student").PrepareInsert()
    for _, stu := range stus {
        _, err := insert.Insert(stu)
        if err != nil {
            fmt.Println("插入错误!\n")
            continue
        }
    }
    insert.Close()
    this.Ctx.WriteString("插入结束!\n")
}

上面的代码相当于sql语句:

insert into student(name, age.hobby) values("银之介", "60", "辣妹"), ....,(园长", "56", "园艺");

Delete

还记得我们刚刚多提交了一次数据插入吗?我们原来的数据stu_id 最大为11, 所以我们删除 stu_id >11 的数据

func (this *ADvancedApiController) GetDelete() {
    orm := orm.NewOrm()
    qs:= orm.QueryTable("student")
    n,err:=qs.Filter("stu_id__gt",11).Delete()
    if err == nil&& n>0 {
        this.Ctx.WriteString("删除成功!\n")

    } else {
        this.Ctx.WriteString("删除失败!\n")
    }
}

Update

现在我们来批量更新下数据,下面我们需要把 stu_id=5 的 Hobby 改为 学习。

func (this *ADvancedApiController) GetUpdate() {
    orm1 := orm.NewOrm()
    qs:= orm1.QueryTable("student")
    n,err:=qs.Filter("stu_id",5).Update(orm.Params{
            "hobby": "学习",
        })
    if err == nil&& n>0 {
        this.Ctx.WriteString("修改成功!\n")

    } else {
        this.Ctx.WriteString("修改失败!\n")
    }
}

看到这里大家应该基本掌握接口的用法了,还有其他部分没演示的,请自行拓展我实在不想写了。

你可能感兴趣的:(#,beego,go)