Golang 语言 Web 框架 beego v2 之读操作(下)

简介: Golang 语言 Web 框架 beego v2 之读操作(下)

04

条件查询


上一小节介绍的查询方式,都没有使用查询条件,本小节内容介绍条件查询,在介绍条件查询之前,先来介绍一下 expr,expr 是 QuerySeter 用于描述字段和描述sql 操作符的一种表达方式。


字段组合的前后顺序依照表的关系,比如 User 表拥有 Profile 的外键,那么对 User 表查询对应的 Profile.Age 为条件,则使用 Profile__Age。


注意,字段的分隔符号使用双下划线 __,除了描述字段, expr 的尾部可以增加操作符以执行对应的 sql 操作。比如 Profile__Age__gt 代表 Profile.Age > 18 的条件查询。


expr 示例代码:


qs.Filter("id", 1) // WHERE id = 1
qs.Filter("profile__age", 18) // WHERE profile.age = 18
qs.Filter("Profile__Age", 18) // 使用字段名和 Field 名都是允许的
qs.Filter("profile__age__gt", 18) // WHERE profile.age > 18
qs.Filter("profile__age__gte", 18) // WHERE profile.age >= 18
qs.Filter("profile__age__in", 18, 20) // WHERE profile.age IN (18, 20)
qs.Filter("profile__age__in", 18, 20).Exclude("profile__lt", 1000)
// WHERE profile.age IN (18, 20) AND NOT profile_id < 1000

注释后面将描述对应的 sql 语句,仅仅是描述 expr 的类似结果,并不代表实际生成的语句。


表达式和操作符

在介绍 QuerySeter 的方法之前,先介绍表达式和操作符,表达式和操作符适用于 QuerySeter 的所有方法。


表达式

  • 等于
  • 大于 gt
  • 大于等于 gte
  • 小于 lt
  • 小于等于 lte
  • IN
  • isnull (true:isnull / false:is not null)


操作符

  • exact 等于(区分字母大小写)

iexact 等于(不区分大小写)

contains Like(区分大小写)

icontains Like( 不区分大小写)

startswith (前置模糊查询,区分大小写)

istartswith(前置模糊查询,不区分大小写)

endswith(后置模糊查询,区分大小写)

iendswith(后置模糊查询,不区分大小写)


QuerySeter 的方法

Filter 包含

Filter 方法用来过滤查询结果,起到「包含条件」的作用。


Exclude 排除

Exclude 方法用来过滤查询结果,起到「排除条件」的作用。


Limit 限制条数

Limit 方法限制最大返回的记录数,默认值为 1000。第二个参数可以设置 offset,需要特别注意的是,这里的 limit / offset 和原生 sql 中的 limit / offset 是反过来的。


Offset 偏移

Offset 方法用来设置偏移量。


OrderBy 排序 "column" means ASC, "-column" means DESC.

OrderBy 方法用于排序,参数使用 expr 表达方式,默认是 ASC 排序规则,在 expr 前面用减号「-」表示 DESC 排序规则。


Distinct 方法

Distinct 方法返回指定字段不重复的查询结果。


Exist 是否存在

Exist 方法用于判断符合查询条件的结果是否存在。


示例代码:


func (u *UserController) Read() {
  o := orm.NewOrm()
  // 条件查询
  var users []models.User
  // Filter 包含
  // 表达式和操作符
  // 等于
  err := o.QueryTable(new(models.User)).Filter("id", 2).One(&users)
  // 大于
  // num, err := o.QueryTable(new(models.User)).Filter("id__gt", 9).All(&users)
  // 大于等于
  // num, err := o.QueryTable(new(models.User)).Filter("id__gte", 9).All(&users)
  // 小于
  // num, err := o.QueryTable(new(models.User)).Filter("id__lt", 5).All(&users)
  // 小于等于
  // num, err := o.QueryTable(new(models.User)).Filter("id__lte", 5).All(&users)
  // IN
  // num, err := o.QueryTable(new(models.User)).Filter("id__in", 2, 4).All(&users)
  // isnull (true:isnull / false: is not null)
  // num, err := o.QueryTable(new(models.User)).Filter("id__isnull", false).All(&users)
  // num, err := o.QueryTable(new(models.User)).Filter("id__isnull", true).All(&users)
  // exact 等于(区分字母大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__exact", "frank").All(&users)
  // iexact 等于(不区分大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__iexact", "frank").All(&users)
  // contains Like(区分大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__contains", "frank").All(&users)
  // icontains Like( 不区分大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__icontains", "frank").All(&users)
  // startswith (前置模糊查询,区分大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__startswith", "fran").All(&users)
  // istartswith(前置模糊查询,不区分大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__istartswith", "fran").All(&users)
  // endswith(后置模糊查询,区分大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__endswith", "er").All(&users)
  // iendswith(后置模糊查询,不区分大小写)
  // num, err := o.QueryTable(new(models.User)).Filter("name__iendswith", "er").All(&users)
  // Exclude 排除
  // num, err := o.QueryTable(new(models.User)).Exclude("name__exact", "frank").All(&users)
  // Limit 限制条数
  // num, err := o.QueryTable(new(models.User)).Limit(4).All(&users)
  // Offset 偏移
  // num, err := o.QueryTable(new(models.User)).Offset(4).All(&users)
  // OrderBy 排序 "column" means ASC, "-column" means DESC.
  // num, err := o.QueryTable(new(models.User)).OrderBy("id").All(&users)
  // num, err := o.QueryTable(new(models.User)).OrderBy("-id").All(&users)
  // Distinct 去重
  // num, err := o.QueryTable(new(models.User)).Filter("id__gt", 9).Distinct().All(&users, "Age")
  // Exist 是否存在
  // isExisted := o.QueryTable(new(models.User)).Filter("name__exact", "frank1").Exist()
  // fmt.Println("isExisted:", isExisted)
  if err != nil {
    log.Fatalln(err.Error())
    return
  }
  fmt.Printf("user:%+v\n", users)
}


05

原生 SQL 查询


beego ORM 原生 SQL 查询,通过获取一个 RawSeter 对象,使用 RawSeter 对象的 Raw 方法,实现原生 SQL 查询。


Raw 方法,参数 1 是原生 sql 语句的字符串,参数 2 是原生 sql 语句的参数,该参数支持模型结构体,切片和数组。


RawSeter 接口的方法:


type RawSeter interface {
    Exec() (sql.Result, error)
    QueryRow(containers ...interface{}) error
    QueryRows(containers ...interface{}) (int64, error)
    SetArgs(...interface{}) RawSeter
    Values(container *[]Params, cols ...string) (int64, error)
    ValuesList(container *[]ParamsList, cols ...string) (int64, error)
    ValuesFlat(container *ParamsList, cols ...string) (int64, error)
    RowsToMap(result *Params, keyCol string, valueCol string) (int64, error)
    RowsToStruct(ptrStruct interface{}, keyCol string, valueCol string) (int64, error)
    Prepare() (RawPreparer, error)
}


接下来,我们来介绍一下 QueryRow 方法和 QueryRows 方法。


QueryRow 方法

QueryRow 方法返回单条查询数据,不定长参数接收指针类型。


示例代码:


func (u *UserController) Read() {
  o := orm.NewOrm()
    var user models.User
  err := o.Raw("SELECT id,name,age FROM beego_user WHERE id = ?", 2).QueryRow(&user)
  if err != nil {
    log.Fatalln(err.Error())
    return
  }
  fmt.Printf("user:%+v\n", user)
}


QueryRows 方法

QueryRows 方法返回多条查询数据,不定长参数接收指针类型。返回结果是查询结果集的数量和错误。


示例代码:


func (u *UserController) Read() {
  o := orm.NewOrm()
  var users []models.User
  ids := []int{1,3,5}
  num, err := o.Raw("SELECT id,name,age FROM beego_user WHERE id IN (?,?,?)", ids).QueryRows(&users)
  if err != nil {
    log.Fatalln(err.Error())
    return
  }
  fmt.Printf("nums:%d user:%+v\n", num, users)
}


06

总结


本文主要介绍 beego ORM 的读操作,包含普通查询、高级查询和原生 SQL 查询,先是介绍了普通查询,然后是介绍高级查询,包含 expr 表达式,QuerySeter 接口和其部分方法的使用,最后介绍了 RawSeter 接口和其部分方法的使用。限于篇幅,没有介绍关联查询和构造查询,关于未提及的内容,读者朋友可以参考官方手册。





目录
相关文章
|
18天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【4月更文挑战第9天】本文对比了Python三大Web框架Django、Flask和Pyramid。Django功能全面,适合快速开发,但学习曲线较陡;Flask轻量灵活,易于入门,但默认配置简单,需自行添加功能;Pyramid兼顾灵活性和可扩展性,适合不同规模项目,但社区及资源相对较少。选择框架应考虑项目需求和开发者偏好。
|
1天前
|
Go 开发者
Golang深入浅出之-Go语言上下文(context)包:处理取消与超时
【4月更文挑战第23天】Go语言的`context`包提供`Context`接口用于处理任务取消、超时和截止日期。通过传递`Context`对象,开发者能轻松实现复杂控制流。本文解析`context`包特性,讨论常见问题和解决方案,并给出代码示例。关键点包括:1) 确保将`Context`传递给所有相关任务;2) 根据需求选择适当的`Context`创建函数;3) 定期检查`Done()`通道以响应取消请求。正确使用`context`包能提升Go程序的控制流管理效率。
6 1
|
2天前
|
安全 Go 开发者
Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello(&quot;Alice&quot;)`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
13 1
|
2天前
|
SQL 关系型数据库 MySQL
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
|
2天前
|
存储 中间件 Go
探索Gin框架:快速构建高性能的Golang Web应用
探索Gin框架:快速构建高性能的Golang Web应用
|
2天前
|
安全 前端开发 JavaScript
在Python Web开发过程中:Web框架相关,如何在Web应用中防止CSRF攻击?
在Python Web开发中防范CSRF攻击的关键措施包括:验证HTTP Referer字段、使用CSRF token、自定义HTTP头验证、利用Web框架的防护机制(如Django的`{% csrf_token %}`)、Ajax请求时添加token、设置安全会话cookie及教育用户提高安全意识。定期进行安全审计和测试以应对新威胁。组合运用这些方法能有效提升应用安全性。
8 0
|
3天前
|
Go 开发者
Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
【4月更文挑战第21天】本文介绍了Go语言中的流程控制语句,包括`if`、`switch`和`for`循环。`if`语句支持简洁的语法和初始化语句,但需注意比较运算符的使用。`switch`语句提供多分支匹配,可省略`break`,同时支持不带表达式的形式。`for`循环有多种形式,如基本循环和`for-range`遍历,遍历时修改原集合可能导致未定义行为。理解并避免易错点能提高代码质量和稳定性。通过实践代码示例,可以更好地掌握Go语言的流程控制。
11 3
Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
|
3天前
|
Go
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
【4月更文挑战第21天】Go语言函数是代码组织的基本单元,用于封装可重用逻辑。本文介绍了函数定义(包括基本形式、命名、参数列表和多返回值)、调用以及匿名函数与闭包。在函数定义时,注意参数命名和注释,避免参数顺序混淆。在调用时,要检查并处理多返回值中的错误。理解闭包原理,小心处理外部变量引用,以提升代码质量和可维护性。通过实践和示例,能更好地掌握Go语言函数。
17 1
Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
|
3天前
|
开发框架 前端开发 数据库
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
|
4天前
|
Go
Golang深入浅出之-Go语言基础语法:变量声明与赋值
【4月更文挑战第20天】本文介绍了Go语言中变量声明与赋值的基础知识,包括使用`var`关键字和简短声明`:=`的方式,以及多变量声明与赋值。强调了变量作用域、遮蔽、初始化与零值的重要性,并提醒读者注意类型推断时的一致性。了解这些概念有助于避免常见错误,提高编程技能和面试表现。
19 0