Fields/FieldsEx Field Filtering

  1. Fields is used to specify the fields of the table to be operated on, including query fields, write fields, update fields, etc.;
  2. FieldsEx is used for specifying exception fields and can be used for query fields, write fields, update fields, etc.;

Fields Example

  1. Suppose the user table has 4 fields: uid, nickname, passport, password.

  2. Query field filtering

    1. // SELECT `uid`,`nickname` FROM `user` ORDER BY `uid` asc
    2. g.Model("user").Fields("uid, nickname").Order("uid asc").All()
  3. Write field filtering

    1. m := g.Map{
    2. "uid" : 10000,
    3. "nickname" : "John Guo",
    4. "passport" : "john",
    5. "password" : "123456",
    6. }
    7. g.Model(table).Fields("nickname,passport,password").Data(m).Insert()
    8. // INSERT INTO `user`(`nickname`,`passport`,`password`) VALUES('John Guo','john','123456')
  4. Supports gdb.Raw input

    1. // SELECT 1 FROM `user` WHERE `id`=10
    2. g.Model("user").Fields(gdb.Raw("1")).Where("id", 10).Value()

FieldsEx Example

  1. Suppose the user table has 4 fields: uid, nickname, passport, password.

  2. Query field exclusion

    1. // SELECT `uid`,`nickname` FROM `user`
    2. g.Model("user").FieldsEx("passport, password").All()
  3. Write field exclusion

    1. m := g.Map{
    2. "uid" : 10000,
    3. "nickname" : "John Guo",
    4. "passport" : "john",
    5. "password" : "123456",
    6. }
    7. g.Model(table).FieldsEx("uid").Data(m).Insert()
    8. // INSERT INTO `user`(`nickname`,`passport`,`password`) VALUES('John Guo','john','123456')

OmitEmpty Empty Value Filtering

When there are empty values like nil, "", 0 in a map/ struct, by default, gdb will consider them as normal input parameters, and hence, they will be updated to the data table. The OmitEmpty feature helps filter out these empty fields before writing data to the database.

Related methods:

  1. func (m *Model) OmitEmpty() *Model
  2. func (m *Model) OmitEmptyWhere() *Model
  3. func (m *Model) OmitEmptyData() *Model

The OmitEmpty method filters out empty data fields from both Where and Data, while the OmitEmptyWhere/OmitEmptyData methods allow specific field filtering.

Insert/Update Operations

Empty values affect insert/update operation methods like Insert, Replace, Update, Save. As in the following operation (taking map as an example, the same applies to struct):

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

To handle empty values, we can use the OmitEmpty method to filter them out. For example, the above example can be modified as follows:

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

For struct data parameters, we can also perform empty value filtering. An operation example:

  1. type User struct {
  2. Id int `orm:"id"`
  3. Passport string `orm:"passport"`
  4. Password string `orm:"password"`
  5. NickName string `orm:"nickname"`
  6. CreateTime string `orm:"create_time"`
  7. UpdateTime string `orm:"update_time"`
  8. }
  9. user := User{
  10. Id : 1,
  11. NickName : "john",
  12. UpdateTime: gtime.Now().String(),
  13. }
  14. g.Model("user").OmitEmpty().Data(user).Insert()
  15. // INSERT INTO `user`(`id`,`nickname`,`update_time`) VALUES(1,'john','2019-10-01 12:00:00')

ORM Model - Fields Filtering - 图1warning

Note that in batch insert/update operations, the OmitEmpty method will be ineffective because fields for each inserted record must be consistent.

Regarding the omitempty tag and the OmitEmpty method:

  1. For empty value filtering in struct, people might think of the omitempty tag. This tag is commonly used for filtering empty values in json conversion and in some third-party ORM libraries for filtering out struct fields with empty values, meaning when a property is empty, it is not converted.
  2. The omitempty tag and the OmitEmpty method achieve the same effect. In ORM operations, we do not recommend using the omitempty tag on struct to control field empty value filtering. Instead, we suggest using the OmitEmpty method. Once the tag is applied, it binds to the struct, and there is no way to control it flexibly; however, with the OmitEmpty method, developers can selectively filter empty values based on the business scenario, allowing for more flexible operations.

Data Query Operations

Empty values also affect data query operations, mainly impacting where condition parameters. We can filter empty values in condition parameters using the OmitEmpty method.

Examples of use:

  1. // SELECT * FROM `user` WHERE `passport`='john' LIMIT 1
  2. r, err := g.Model("user").Where(g.Map{
  3. "nickname" : "",
  4. "passport" : "john",
  5. }).OmitEmpty().One()
  1. type User struct {
  2. Id int `orm:"id"`
  3. Passport string `orm:"passport"`
  4. Password string `orm:"password"`
  5. NickName string `orm:"nickname"`
  6. CreateTime string `orm:"create_time"`
  7. UpdateTime string `orm:"update_time"`
  8. }
  9. user := User{
  10. Passport : "john",
  11. }
  12. r, err := g.Model("user").OmitEmpty().Where(user).One()
  13. // SELECT * FROM `user` WHERE `passport`='john' LIMIT 1

OmitNil Empty Value Filtering

Overview

When there are empty values like nil in a map/ struct, by default, gdb will consider them as normal input parameters, and hence, they will be updated to the data table. The OmitNil feature helps filter out these empty fields before writing data to the database. The difference between OmitNil and OmitEmpty is that OmitNil only filters fields with nil values, while other empty values like "", 0 will not be filtered.

Related methods:

  1. func (m *Model) OmitNil() *Model
  2. func (m *Model) OmitNilWhere() *Model
  3. func (m *Model) OmitNilData() *Model

The OmitNil method filters out empty fields from both Where and Data, while the OmitNilWhere/OmitNilData methods allow specific field filtering.

Using do Objects for Field Filtering

If you use the GoFrame project directory and use the gf gen dao or make dao command, the corresponding table dao/entity/do files will be automatically generated based on the configured database. If do objects are used in database operations, unassigned fields will be automatically filtered. For example:

Generated do object struct definition

  1. // User is the golang structure of table user for DAO operations like Where/Data.
  2. type User struct {
  3. g.Meta `orm:"table:user, do:true"`
  4. Id interface{} // User ID
  5. Passport interface{} // User Passport
  6. Password interface{} // User Password
  7. Nickname interface{} // User Nickname
  8. CreateAt *gtime.Time // Created Time
  9. UpdateAt *gtime.Time // Updated Time
  10. }

Data Insertion:

  1. dao.User.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
  2. _, err = dao.User.Ctx(ctx).Data(do.User{
  3. Passport: in.Passport,
  4. Password: in.Password,
  5. Nickname: in.Nickname,
  6. }).Insert()
  7. return err
  8. })

Data Query:

  1. var user *entity.User
  2. err = dao.User.Ctx(ctx).Where(do.User{
  3. Passport: in.Passport,
  4. Password: in.Password,
  5. }).Scan(&user)

Filter Field Filtering (Built-in)

gdb can automatically synchronize the table structure to the program cache (cache does not expire until the program restarts/redeploys) and can filter out non-compliant table structure items from the submitted parameters. This feature can be achieved using the Filter method. It is commonly used in scenarios involving input map/struct/[]map/[]string parameters for insert/delete operations.

Usage example, suppose the user table has 4 fields: uid, nickname, passport, password:

  1. r, err := g.Model("user").Filter().Data(g.Map{
  2. "id" : 1,
  3. "uid" : 1,
  4. "passport" : "john",
  5. "password" : "123456",
  6. }).Insert()
  7. // INSERT INTO user(uid,passport,password) VALUES(1, "john", "123456")

Here, id is a non-existent field, and it will be filtered out during data insertion to prevent execution errors in the constructed SQL.

ORM Model - Fields Filtering - 图2tip

The database is not designed to automatically filter for the Data method. Instead, developers need to specify filtering manually by calling the Filter method. This aims to kindly remind developers of possible mistakes/wrongly passed field names. Automatically filtering may cause unpredictable business logic anomalies, for example, the Filter method can cause the automatic filtering of essential fields due to incorrect spelling of field names, leading to incomplete data in the database.

ORM Model - Fields Filtering - 图3warning

From version GoFrame v1.15.7, based on overall community feedback, to enhance component usability, the filter feature is enabled by default and no longer needs to be explicitly called, making the Filter method deprecated.