阅读(302) (8)

GoFrame 链式操作-字段过滤

2022-04-01 16:04:47 更新

Fields/FieldsEx字段过滤

Fields用于指定需要操作的表字段,包括查询字段、写入字段、更新字段等过滤;

FieldsEx用于例外的字段指定,可用于查询字段、写入字段、更新字段等过滤;

Fields示例

  • 假如​user​表有4个字段​uid​, ​nickname​, ​passport​, ​password​。
  • 查询字段过滤
 // SELECT `uid`,`nickname` FROM `user` ORDER BY `uid` asc
 db.Table("user").Fields("uid, nickname").Order("uid asc").All()
  • 写入字段过滤
m := g.Map{
     "uid"      : 10000,
     "nickname" : "John Guo",
     "passport" : "john",
     "password" : "123456",
 }
 db.Table(table).Fields("nickname,passport,password").Data(m).Insert()
 // INSERT INTO `user`(`nickname`,`passport`,`password`) VALUES('John Guo','john','123456')

FieldsEx示例

  • 假如​user​表有4个字段​uid​, ​nickname​, ​passport​, ​password​。
  • 查询字段排除
 // SELECT `uid`,`nickname` FROM `user`
 db.Table("user").FieldsEx("passport, password").All()
  • 写入字段排除
 m := g.Map{
     "uid"      : 10000,
     "nickname" : "John Guo",
     "passport" : "john",
     "password" : "123456",
 }
 db.Table(table).FieldsEx("uid").Data(m).Insert()
 // INSERT INTO `user`(`nickname`,`passport`,`password`) VALUES('John Guo','john','123456')

OmitEmpty空值过滤

当 ​map/struct​ 中存在空值如 ​nil​,​""​,​0​ 时,默认情况下,​gdb​将会将其当做正常的输入参数,因此这些参数也会被更新到数据表。​OmitEmpty​特性可以在将数据写入到数据库之前过滤空值数据的字段。

相关方法:

func (m *Model) OmitEmpty() *Model
func (m *Model) OmitEmptyWhere() *Model
func (m *Model) OmitEmptyData() *Model 

OmitEmpty​方法会同时过滤​Where​及​Data​中的空值数据,而通过​OmitEmptyWhere/OmitEmptyData​方法可以执行特定的字段过滤。

写入/更新操作

空值会影响于写入/更新操作方法,如​Insert​, ​Replace​, ​Update​, ​Save​操作。如以下操作(以​map​为例,​struct​同理):

// UPDATE `user` SET `name`='john',update_time=null WHERE `id`=1
db.Table("user").Data(g.Map{
    "name"        : "john",
    "update_time" : nil,
}).Where("id", 1).Update()

针对空值情况,我们可以通过​OmitEmpty​方法来过滤掉这些空值。例如,以上示例可以修改为:

// UPDATE `user` SET `name`='john' WHERE `id`=1
db.Table("user").OmitEmpty().Data(g.Map{
    "name"        : "john",
    "update_time" : nil,
}).Where("id", 1).Update()

对于​struct​数据参数,我们也可以进行空值过滤。操作示例:

type User struct {
    Id         int    `orm:"id"`
    Passport   string `orm:"passport"`
    Password   string `orm:"password"`
    NickName   string `orm:"nickname"`
    CreateTime string `orm:"create_time"`
    UpdateTime string `orm:"update_time"`
}
user := User{
    Id        : 1,
    NickName  : "john",
    UpdateTime: gtime.Now().String(),
}
db.Table("user").OmitEmpty().Data(user).Insert()
// INSERT INTO `user`(`id`,`nickname`,`update_time`) VALUES(1,'john','2019-10-01 12:00:00')

注意哟,批量写入/更新操作中​OmitEmpty​方法将会失效,因为在批量操作中,必须保证每个写入记录的字段是统一的。

关于​omitempty​标签与​OmitEmpty​方法:

  1. 针对于​struct​的空值过滤大家会想到​omitempty​的标签。该标签常用于​json​转换的空值过滤,也在某一些第三方的​ORM​库中用作​struct​到数据表字段的空值过滤,即当属性为空值时不做转换。
  2. omitempty​标签与​OmitEmpty​方法所达到的效果是一样的。在​ORM​操作中,我们不建议对​struct​使用​omitempty​的标签来控制字段的空值过滤,而建议使用​OmitEmpty​方法来做控制。因为该标签一旦加上之后便绑定到了​struct​上,没有办法做灵活控制;而通过​OmitEmpty​方法使得开发者可以选择性地、根据业务场景对​struct​做空值过滤,操作更加灵活。

数据查询操作

空值也会影响数据查询操作,主要是影响​where​条件参数。我们可以通过​OmitEmpty​方法过滤条件参数中的空值。

使用示例:

// SELECT * FROM `user` WHERE `passport`='john' LIMIT 1
r, err := db.Table("user").Where(g.Map{
    "nickname" : "",
    "passport" : "john",
}).OmitEmpty().One()
type User struct {
    Id         int    `orm:"id"`
    Passport   string `orm:"passport"`
    Password   string `orm:"password"`
    NickName   string `orm:"nickname"`
    CreateTime string `orm:"create_time"`
    UpdateTime string `orm:"update_time"`
}
user := User{
    Passport : "john",
}
r, err := db.Table("user").OmitEmpty().Where(user).One()
// SELECT * FROM `user` WHERE `passport`='john' LIMIT 1

OmitNil空值过滤

当 ​map/struct​ 中存在空值如nil​时,默认情况下,​gdb​将会将其当做正常的输入参数,因此这些参数也会被更新到数据表。​OmitNil​特性可以在将数据写入到数据库之前过滤空值数据的字段。与​OmitEmpty​特性的区别在于,​OmitNil​只会过滤值为nil的空值字段,其他空值如​""​,​0​并不会被过滤。

相关方法:

func (m *Model) OmitNil() *Model
func (m *Model) OmitNilWhere() *Model
func (m *Model) OmitNilData() *Model 

OmitEmpty​方法会同时过滤​Where​及​Data​中的空值数据,而通过​OmitEmptyWhere/OmitEmptyData​方法可以执行特定的字段过滤。

Filter字段过滤(已内置)

gdb​可以自动同步数据表结构到程序缓存中(缓存不过期,直至程序重启/重新部署),并且可以过滤提交参数中不符合表结构的数据项,该特性可以使用​Filter​方法实现。常用于新增/删除操作中输入​map/struct/[]map/[]string​参数类型的场景。

使用示例,假如​user​表有4个字段​uid​, ​nickname​, ​passport​, ​password​:

r, err := db.Table("user").Filter().Data(g.Map{
    "id"          : 1,
    "uid"         : 1,
    "passport"    : "john",
    "password"    : "123456",
}).Insert()
// INSERT INTO user(uid,passport,password) VALUES(1, "john", "123456")

其中id为不存在的字段,在写入数据时将会被过滤掉,不至于被构造成写入​SQL​中产生执行错误。

数据库没有设计为​Data​方法做自动过滤,而是需要开发者调用​Filter​方法来手动指定过滤,目的是友好地提醒开发者可能误写/传递错误了字段名称。如果强制性的自动过滤可能会引起难以预料的业务逻辑异常,例如,由于字段名称拼写错误导致自动过滤了本来需要输入的字段,导致写入数据库的数据不完整。

从​GoFrame v1.15.7​版本开始,根据社区整体反馈,为提高组件易用性,​filter​特性被设置为默认开启,不再需要显示调用,​Filter​方法已被标记废弃。