user, err := u.WithContext(ctx).Where(u.ID.Eq(10)).First() // SELECT * FROM users WHERE id = 10;
users, err := u.WithContext(ctx).Where(u.ID.In(1,2,3)).Find() // SELECT * FROM users WHERE id IN (1,2,3);
如果主键是字符串(例如像uuid),查询将被写成如下:
user, err := u.WithContext(ctx).Where(u.ID.Eq("1b74413f-f3b8-409f-ac47-e8c062e3472a")).First() // SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";
检索全部对象
u := query.User
// Get all records users, err := u.WithContext(ctx).Find() // SELECT * FROM users;
// Get first matched record user, err := u.WithContext(ctx).Where(u.Name.Eq("modi")).First() // SELECT * FROM users WHERE name = 'modi' ORDER BY id LIMIT 1;
// Get all matched records users, err := u.WithContext(ctx).Where(u.Name.Neq("modi")).Find() // SELECT * FROM users WHERE name <> 'modi';
// IN users, err := u.WithContext(ctx).Where(u.Name.In("modi", "zhangqiang")).Find() // SELECT * FROM users WHERE name IN ('modi','zhangqiang');
// LIKE users, err := u.WithContext(ctx).Where(u.Name.Like("%modi%")).Find() // SELECT * FROM users WHERE name LIKE '%modi%';
// AND users, err := u.WithContext(ctx).Where(u.Name.Eq("modi"), u.Age.Gte(17)).Find() // SELECT * FROM users WHERE name = 'modi' AND age >= 17;
// Time users, err := u.WithContext(ctx).Where(u.Birthday.Gt(birthTime).Find() // SELECT * FROM users WHERE birthday > '2000-01-01 00:00:00';
// BETWEEN users, err := u.WithContext(ctx).Where(u.Birthday.Between(lastWeek, today)).Find() // SELECT * FROM users WHERE birthday BETWEEN '2000-01-01 00:00:00' AND '2000-01-08 00:00:00';
Not 条件
构建 NOT 条件,用法与 Where 类似
u := query.User
user, err := u.WithContext(ctx).Not(u.Name.Eq("modi")).First() // SELECT * FROM users WHERE NOT name = "modi" ORDER BY id LIMIT 1;
// Not In users, err := u.WithContext(ctx).Not(u.Name.In("modi", "zhangqiang")).Find() // SELECT * FROM users WHERE name NOT IN ("modi", "zhangqiang");
// Not In slice of primary keys user, err := u.WithContext(ctx).Not(u.ID.In(1,2,3)).First() // SELECT * FROM users WHERE id NOT IN (1,2,3) ORDER BY id LIMIT 1;
Or 条件
u := query.User
users, err := u.WithContext(ctx).Where(u.Role.Eq("admin")).Or(u.Role.Eq("super_admin")).Find() // SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
// SELECT * FROM `pizzas` WHERE (pizza = "pepperoni" AND (size = "small" OR size = "medium")) OR (pizza = "hawaiian" AND size = "xlarge")
查询特定字段
Select 允许您指定从数据库中取出哪些字段, 默认情况下,GORM 会检索所有字段。
u := query.User
users, err := u.WithContext(ctx).Select(u.Name, u.Age).Find() // SELECT name, age FROM users;
u.WithContext(ctx).Select(u.Age.Avg()).Rows() // SELECT Avg(age) FROM users;
多字段IN
u := query.User
users, err := u.WithContext(ctx).Where(u.WithContext(ctx).Columns(u.ID, u.Name).In(field.Values([][]interface{}{{1, "modi"}, {2, "zhangqiang"}}))).Find() // SELECT * FROM `users` WHERE (`id`, `name`) IN ((1,'humodi'),(2,'tom'));
JSON 查询
u := query.User
users, err := u.WithContext(ctx).Where(gen.Cond(datatypes.JSONQuery("attributes").HasKey("role"))...).Find() // SELECT * FROM `users` WHERE JSON_EXTRACT(`attributes`,'$.role') IS NOT NULL;
Order
指定从数据库检索记录时的排序方式
u := query.User
users, err := u.WithContext(ctx).Order(u.Age.Desc(), u.Name).Find() // SELECT * FROM users ORDER BY age DESC, name;
// Multiple orders users, err := u.WithContext(ctx).Order(u.Age.Desc()).Order(u.Name).Find() // SELECT * FROM users ORDER BY age DESC, name;
按字符串获取字段
u := query.User
orderCol, ok := u.GetFieldByName(orderColStr) // maybe orderColStr == "id" if !ok { // User doesn't contains orderColStr }
users, err := u.WithContext(ctx).Order(orderCol).Find() // SELECT * FROM users ORDER BY age;
// OR Desc users, err := u.WithContext(ctx).Order(orderCol.Desc()).Find() // SELECT * FROM users ORDER BY age DESC;
// Cancel offset condition with -1 users, err := u.WithContext(ctx).Offset(10).Offset(-1).Find() // SELECT * FROM users;
Group By & Having
u := query.User
var users []struct { Name string Total int } err := u.WithContext(ctx).Select(u.Name, u.ID.Count().As("total")).Group(u.Name).Scan(&users) // SELECT name, count(id) as total FROM `users` GROUP BY `name`
err := u.WithContext(ctx).Select(u.Name, u.Age.Sum().As("total")).Where(u.Name.Like("%modi%")).Group(u.Name).Scan(&users) // SELECT name, sum(age) as total FROM `users` WHERE name LIKE "%modi%" GROUP BY `name`
err := u.WithContext(ctx).Select(u.Name, u.Age.Sum().As("total")).Group(u.Name).Having(u.Name.Eq("group")).Scan(&users) // SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "group"
rows, err := u.WithContext(ctx).Select(u.Birthday.As("date"), u.Age.Sum().As("total")).Group(u.Birthday).Rows() for rows.Next() { ... }
o := query.Order
rows, err := o.WithContext(ctx).Select(o.CreateAt.Date().As("date"), o.Amount.Sum().As("total")).Group(o.CreateAt.Date()).Having(u.Amount.Sum().Gt(100)).Rows() for rows.Next() { ... }
q := query u := q.User e := q.Email c := q.CreditCard
type Result struct { Name string Email string ID int64 }
var result Result
err := u.WithContext(ctx).Select(u.Name, e.Email).LeftJoin(e, e.UserID.EqCol(u.ID)).Scan(&result) // SELECT users.name, emails.email FROM `users` left join emails on emails.user_id = users.id
// self join var result Result u2 := u.As("u2") err := u.WithContext(ctx).Select(u.Name, u2.ID).LeftJoin(u2, u2.ID.EqCol(u.ID)).Scan(&result) // SELECT users.name, u2.id FROM `users` left join `users` u2 on u2.id = users.id
//join with sub query var result Result e2 := e.As("e2") err := u.WithContext(ctx).Select(u.Name, e2.Email).LeftJoin(e.WithContext(ctx).Select(e.Email, e.UserID).Where(e.UserID.Gt(100)).As("e2"), e2.UserID.EqCol(u.ID)).Scan(&result) // SELECT users.name, e2.email FROM `users` left join (select email,user_id from emails where user_id > 100) as e2 on e2.user_id = users.id
active := field.NewBool("user", "active") // `user`.`active` = TRUE active.Is(true) // NOT `user`.`active` active.Not() // `user`.`active` AND TRUE active.And(true)
子查询
子查询可以嵌套在查询中,GEN 可以在使用 Dao 对象作为参数时生成子查询
o := query.Order u := query.User
orders, err := o.WithContext(ctx).Where(o.WithContext(ctx).Columns(o.Amount).Gt(o.WithContext(ctx).Select(o.Amount.Avg())).Find() // SELECT * FROM "orders" WHERE amount > (SELECT AVG(amount) FROM "orders");
subQuery := u.WithContext(ctx).Select(u.Age.Avg()).Where(u.Name.Like("name%")) users, err := u.WithContext(ctx).Select(u.Age.Avg().As("avgage")).Group(u.Name).Having(u.WithContext(ctx).Columns(u.Age.Avg()).Gt(subQuery).Find() // SELECT AVG(age) as avgage FROM `users` GROUP BY `name` HAVING AVG(age) > (SELECT AVG(age) FROM `users` WHERE name LIKE "name%")
// Select users with orders between 100 and 200 subQuery1 := o.WithContext(ctx).Select(o.ID).Where(o.UserID.EqCol(u.ID), o.Amount.Gt(100)) subQuery2 := o.WithContext(ctx).Select(o.ID).Where(o.UserID.EqCol(u.ID), o.Amount.Gt(200)) u.WithContext(ctx).Where(gen.Exists(subQuery1)).Not(gen.Exists(subQuery2)).Find() // SELECT * FROM `users` WHERE EXISTS (SELECT `orders`.`id` FROM `orders` WHERE `orders`.`user_id` = `users`.`id` AND `orders`.`amount` > 100 AND `orders`.`deleted_at` IS NULL) AND NOT EXISTS (SELECT `orders`.`id` FROM `orders` WHERE `orders`.`user_id` = `users`.`id` AND `orders`.`amount` > 200 AND `orders`.`deleted_at` IS NULL) AND `users`.`deleted_at` IS NULL
From 子查询
GORM 允许您在 Table 方法中使用子查询作为表查询,例如:
u := query.User p := query.Pet
users, err := gen.Table(u.WithContext(ctx).Select(u.Name, u.Age).As("u")).Where(u.Age.Eq(18)).Find() // SELECT * FROM (SELECT `name`,`age` FROM `users`) as u WHERE `age` = 18
subQuery1 := u.WithContext(ctx).Select(u.Name) subQuery2 := p.WithContext(ctx).Select(p.Name) users, err := gen.Table(subQuery1.As("u"), subQuery2.As("p")).Find() db.Table("(?) as u, (?) as p", subQuery1, subQuery2).Find(&User{}) // SELECT * FROM (SELECT `name` FROM `users`) as u, (SELECT `name` FROM `pets`) as p
// User not found, initialize it with given conditions and Attrs u.WithContext(ctx).Attrs(field.Attrs(&model.User{Age: 20})).Where(u.Name.Eq("non_existing")).FirstOrInit() // SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1; // user -> User{Name: "non_existing", Age: 20}
// User not found, initialize it with given conditions and Attrs u.WithContext(ctx).Attrs(u.Age.Value(20).Where(u.Name.Eq("non_existing")).FirstOrInit() // SELECT * FROM USERS WHERE name = 'non_existing' ORDER BY id LIMIT 1; // user -> User{Name: "non_existing", Age: 20}
// Found user with `name` = `gen`, attributes will be ignored u.WithContext(ctx).Attrs(field.Attrs(&model.User{Age: 20})).Where(u.Name.Eq("gen")).FirstOrInit() // SELECT * FROM USERS WHERE name = 'gen' ORDER BY id LIMIT 1; // user -> User{ID: 111, Name: "gen", Age: 18}
// User not found, initialize it with give conditions and Assign attributes u.WithContext(ctx).Assign(field.Attrs(map[string]interface{}{"age": 20})).Where(u.Name.Eq("non_existing")).FirstOrInit() // user -> User{Name: "non_existing", Age: 20}
// Found user with `name` = `gen`, update it with Assign attributes u.WithContext(ctx).Assign(field.Attrs(&model.User{Name: "gen_assign"}).Select(dal.User.ALL)).Where(u.Name.Eq("gen")).FirstOrInit()
// SELECT * FROM USERS WHERE name = gen' ORDER BY id LIMIT 1; // user -> User{ID: 111, Name: "gen", Age: 20}
// User not found, create it with give conditions and Attrs u.WithContext(ctx).Attrs(field.Attrs(&model.User{Age: 20})).Where(u.Name.Eq("non_existing")).FirstOrCreate() // SELECT * FROM users WHERE name = 'non_existing' ORDER BY id LIMIT 1; // INSERT INTO "users" (name, age) VALUES ("non_existing", 20); // user -> User{ID: 112, Name: "non_existing", Age: 20}
// Found user with `name` = `gen`, attributes will be ignored u.WithContext(ctx).Attrs(field.Attrs(&model.User{Age: 20})).Where(u.Name.Eq("gen")).FirstOrCreate() // SELECT * FROM users WHERE name = 'gen' ORDER BY id LIMIT 1; // user -> User{ID: 111, Name: "gen", Age: 18}
不管是否找到记录,Assign 都会将属性赋值给 struct,并将结果写回数据库
// User not found, initialize it with give conditions and Assign attributes u.WithContext(ctx).Assign(field.Attrs(&model.User{Age: 20})).Where(u.Name.Eq("non_existing")).FirstOrCreate() // SELECT * FROM users WHERE name = 'non_existing' ORDER BY id LIMIT 1; // INSERT INTO "users" (name, age) VALUES ("non_existing", 20); // user -> User{ID: 112, Name: "non_existing", Age: 20}
// Found user with `name` = `gen`, update it with Assign attributes u.WithContext(ctx).Assign(field.Attrs(&model.User{Age: 20})).Where(u.Name.Eq("gen")).FirstOrCreate() // SELECT * FROM users WHERE name = 'gen' ORDER BY id LIMIT 1; // UPDATE users SET age=20 WHERE id = 111; // user -> User{ID: 111, Name: "gen", Age: 20}
// Found user with `name` = `gen`, update it with Assign attributes u.WithContext(ctx).Assign(u.Age.Value(20)).Where(u.Name.Eq("gen")).FirstOrCreate() // SELECT * FROM users WHERE name = 'gen' ORDER BY id LIMIT 1; // UPDATE users SET age=20 WHERE id = 111; // user -> User{ID: 111, Name: "gen", Age: 20}
Struct & Map Conditions
// Struct u.WithContext(ctx).Where(field.Attrs(&User{Name: "gen", Age: 20})).First() // SELECT * FROM users WHERE name = "gen" AND age = 20 ORDER BY id LIMIT 1;
// Map u.WithContext(ctx).Where(field.Attrs(map[string]interface{}{"name": "gen", "age": 20})).Find() // SELECT * FROM users WHERE name = "gen" AND age = 20;