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条件を構築します。 `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';
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;
タプル問合せ
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;
順序
データベースからレコードを取得する際の順序を指定します。
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;
グループ化と絞り込み
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
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` メソッドを使用してFROM句でサブクエリを使用できます。 例えば、
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}
// Found user with `name` = `gen` result := u.WithContext(ctx).Where(u.Name.Eq(jinzhu)).FirstOrCreate() // user -> User{ID: 111, Name: "gen", "Age": 18} // result.RowsAffected // => 0
// 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}
// 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 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;