mirror of https://github.com/go-gorm/gorm.git
Better README
This commit is contained in:
parent
b4981259de
commit
a135087af4
425
README.md
425
README.md
|
@ -18,7 +18,7 @@ Yet Another ORM library for Go, aims for developer friendly
|
||||||
* Prevent SQL Injection
|
* Prevent SQL Injection
|
||||||
* Goroutines friendly
|
* Goroutines friendly
|
||||||
* Database Pool
|
* Database Pool
|
||||||
* Convention Over Configuration (CoC)
|
* Convention Over Configuration
|
||||||
|
|
||||||
## Basic Usage
|
## Basic Usage
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ type User struct { // TableName: `users`, gorm will pluralize struc
|
||||||
DeletedAt time.Time // DeletedAt: Time of record is deleted, refer Soft Delete for more
|
DeletedAt time.Time // DeletedAt: Time of record is deleted, refer Soft Delete for more
|
||||||
Email []Email // Embedded structs
|
Email []Email // Embedded structs
|
||||||
BillingAddress Address // Embedded struct
|
BillingAddress Address // Embedded struct
|
||||||
BillingAddressId int64 // Embedded struct's foreign key
|
BillingAddressId int64 // Embedded struct BillingAddress's foreign key
|
||||||
ShippingAddress Address // Embedded struct
|
ShippingAddress Address // Embedded struct
|
||||||
ShippingAddressId int64 // Embedded struct's foreign key
|
ShippingAddressId int64 // Embedded struct ShippingAddress's foreign key
|
||||||
}
|
}
|
||||||
|
|
||||||
type Email struct { // TableName: `emails`
|
type Email struct { // TableName: `emails`
|
||||||
|
@ -92,36 +92,26 @@ user := User{Name: "jinzhu", Age: 18, Birthday: time.Now()}
|
||||||
db.Save(&user)
|
db.Save(&user)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update
|
|
||||||
|
|
||||||
```go
|
|
||||||
user.Name = "jinzhu 2"
|
|
||||||
db.Save(&user)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Delete
|
|
||||||
|
|
||||||
```go
|
|
||||||
db.Delete(&user)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Query
|
## Query
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Get the first record
|
// Get the first record
|
||||||
db.First(&user)
|
db.First(&user)
|
||||||
//// SELECT * FROM USERS LIMIT 1;
|
//// SELECT * FROM users LIMIT 1;
|
||||||
|
// Search table `users` are guessed from the out struct's name.
|
||||||
|
// You are possible to specify the table name with Model() if no out struct for some methods like Pluck()
|
||||||
|
// Or set table name with Table(), if so, it will ignore the out struct's type even have it. more details later.
|
||||||
|
|
||||||
// Get All records
|
// Get All records
|
||||||
db.Find(&users)
|
db.Find(&users)
|
||||||
//// SELECT * FROM USERS;
|
//// SELECT * FROM users;
|
||||||
|
|
||||||
// Using a Primary Key
|
// Using a Primary Key
|
||||||
db.First(&user, 10)
|
db.First(&user, 10)
|
||||||
//// SELECT * FROM USERS WHERE id = 10;
|
//// SELECT * FROM users WHERE id = 10;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Where (SQL like condition)
|
### Query With Where (SQL like condition)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Get the first matched record
|
// Get the first matched record
|
||||||
|
@ -139,10 +129,6 @@ db.Where("name <> ?", "jinzhu").Find(&users)
|
||||||
db.Where("name in (?)", []string["jinzhu", "jinzhu 2"]).Find(&users)
|
db.Where("name in (?)", []string["jinzhu", "jinzhu 2"]).Find(&users)
|
||||||
//// SELECT * FROM users WHERE name IN ('jinzhu', 'jinzhu 2');
|
//// SELECT * FROM users WHERE name IN ('jinzhu', 'jinzhu 2');
|
||||||
|
|
||||||
// IN For Primary Key
|
|
||||||
db.Where([]int64{20, 21, 22}).Find(&users)
|
|
||||||
//// SELECT * FROM users WHERE id IN (20, 21, 22);
|
|
||||||
|
|
||||||
// LIKE
|
// LIKE
|
||||||
db.Where("name LIKE ?", "%jin%").Find(&users)
|
db.Where("name LIKE ?", "%jin%").Find(&users)
|
||||||
//// SELECT * FROM users WHERE name LIKE "%jin%";
|
//// SELECT * FROM users WHERE name LIKE "%jin%";
|
||||||
|
@ -152,7 +138,7 @@ db.Where("name = ? and age >= ?", "jinzhu", "22").Find(&users)
|
||||||
//// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
|
//// SELECT * FROM users WHERE name = 'jinzhu' AND age >= 22;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Where (Struct & Map)
|
### Query With Where (Struct & Map)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Search with struct
|
// Search with struct
|
||||||
|
@ -162,12 +148,16 @@ db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
|
||||||
// Search with map
|
// Search with map
|
||||||
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
|
db.Where(map[string]interface{}{"name": "jinzhu", "age": 20}).Find(&users)
|
||||||
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
|
//// SELECT * FROM users WHERE name = "jinzhu" AND age = 20;
|
||||||
|
|
||||||
|
// IN For Primary Key
|
||||||
|
db.Where([]int64{20, 21, 22}).Find(&users)
|
||||||
|
//// SELECT * FROM users WHERE id IN (20, 21, 22);
|
||||||
```
|
```
|
||||||
|
|
||||||
### Not
|
### Query With Not
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Not Equal
|
// Attribute Not Equal
|
||||||
db.Not("name", "jinzhu").First(&user)
|
db.Not("name", "jinzhu").First(&user)
|
||||||
//// SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;
|
//// SELECT * FROM users WHERE name <> "jinzhu" LIMIT 1;
|
||||||
|
|
||||||
|
@ -191,7 +181,7 @@ db.Not(User{Name: "jinzhu"}).First(&user)
|
||||||
//// SELECT * FROM users WHERE name <> "jinzhu";
|
//// SELECT * FROM users WHERE name <> "jinzhu";
|
||||||
```
|
```
|
||||||
|
|
||||||
### Inline Search Condition
|
### Inline Search
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Find with primary key
|
// Find with primary key
|
||||||
|
@ -215,6 +205,117 @@ db.Find(&users, map[string]interface{}{"age": 20})
|
||||||
//// SELECT * FROM users WHERE age = 20;
|
//// SELECT * FROM users WHERE age = 20;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Query With Or
|
||||||
|
|
||||||
|
```
|
||||||
|
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
|
||||||
|
//// SELECT * FROM users WHERE role = 'admin' OR role = 'super_admin';
|
||||||
|
|
||||||
|
// Or With Struct
|
||||||
|
db.Where("name = 'jinzhu'").Or(User{Name: "jinzhu 2"}).Find(&users)
|
||||||
|
//// SELECT * FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2';
|
||||||
|
|
||||||
|
// Or With Map
|
||||||
|
db.Where("name = 'jinzhu'").Or(map[string]interface{}{"name": "jinzhu 2"}).Find(&users)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Query Chains
|
||||||
|
|
||||||
|
Gorm has a chainable API, so you could write query in chain
|
||||||
|
|
||||||
|
```go
|
||||||
|
db.Where("name <> ?", "jinzhu").Where("age >= ? and role <> ?", 20, "admin").Find(&users)
|
||||||
|
//// SELECT * FROM users WHERE name <> 'jinzhu' AND age >= 20 AND role <> 'admin';
|
||||||
|
|
||||||
|
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Not("name = ?", "jinzhu").Find(&users)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update
|
||||||
|
|
||||||
|
### Update an existing struct
|
||||||
|
|
||||||
|
```go
|
||||||
|
user.Name = "jinzhu 2"
|
||||||
|
user.Age = 100
|
||||||
|
db.Save(&user)
|
||||||
|
//// UPDATE users SET name='jinzhu 2', age=100 WHERE id=111;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update one attribute with `Update`
|
||||||
|
|
||||||
|
```
|
||||||
|
// Update an existing struct's name if name is different
|
||||||
|
db.Model(&user).Update("name", "hello")
|
||||||
|
//// UPDATE users SET name='hello' WHERE id=111;
|
||||||
|
|
||||||
|
// Find out a struct, and update it if name is different
|
||||||
|
db.First(&user, 111).Update("name", "hello")
|
||||||
|
//// SELECT * FROM users LIMIT 1;
|
||||||
|
//// UPDATE users SET name='hello' WHERE id=111;
|
||||||
|
|
||||||
|
// Update a record
|
||||||
|
db.Table("users").Where(10).Update("name", "hello")
|
||||||
|
//// UPDATE users SET name='hello' WHERE id = 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update multiple attributes with `Updates`
|
||||||
|
|
||||||
|
```
|
||||||
|
// Update an existing record if have any different attributes
|
||||||
|
db.Model(&user).Updates(User{Name: "hello", Age: 18})
|
||||||
|
//// UPDATE users SET name='hello', age=18 WHERE id = 111;
|
||||||
|
|
||||||
|
// Update with Map
|
||||||
|
db.Table("users").Where(10).Updates(map[string]interface{}{"name": "hello", "age": 18})
|
||||||
|
//// UPDATE users SET name='hello', age=18 WHERE id = 10;
|
||||||
|
|
||||||
|
// Update with Struct
|
||||||
|
db.Model(User{}).Updates(User{Name: "hello", Age: 18})
|
||||||
|
//// UPDATE users SET name='hello', age=18;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Delete
|
||||||
|
|
||||||
|
### Delete an existing struct
|
||||||
|
|
||||||
|
```go
|
||||||
|
db.Delete(&email)
|
||||||
|
// DELETE from emails where id=10;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Batch Delete with search
|
||||||
|
|
||||||
|
```go
|
||||||
|
db.Where("email LIKE ?", "%jinzhu%").Delete(Email{})
|
||||||
|
// DELETE from emails where email LIKE "%jinhu%";
|
||||||
|
```
|
||||||
|
|
||||||
|
### Soft Delete
|
||||||
|
|
||||||
|
If a struct have DeletedAt field, it will get soft delete ability automatically!
|
||||||
|
For those don't have the filed, will be deleted from database permanently
|
||||||
|
|
||||||
|
```go
|
||||||
|
db.Delete(&user)
|
||||||
|
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE id = 111;
|
||||||
|
|
||||||
|
// Batch delete when search
|
||||||
|
db.Where("age = ?", 20).Delete(&User{})
|
||||||
|
//// UPDATE users SET deleted_at="2013-10-29 10:23" WHERE age = 20;
|
||||||
|
|
||||||
|
// For structs have DeletedAt field, when do query, will ignore deleted records by default
|
||||||
|
db.Where("age = 20").Find(&user)
|
||||||
|
//// SELECT * FROM users WHERE age = 100 AND (deleted_at IS NULL AND deleted_at <= '0001-01-02');
|
||||||
|
|
||||||
|
// Find out all records including those deleted with Unscoped
|
||||||
|
db.Unscoped().Where("age = 20").Find(&users)
|
||||||
|
//// SELECT * FROM users WHERE age = 20;
|
||||||
|
|
||||||
|
// Permanently delete a record with Unscoped
|
||||||
|
db.Unscoped().Delete(&order)
|
||||||
|
// DELETE FROM orders WHERE id=10;
|
||||||
|
```
|
||||||
|
|
||||||
## FirstOrInit
|
## FirstOrInit
|
||||||
|
|
||||||
Try to load the first record, if fails, initialize struct with search conditions.
|
Try to load the first record, if fails, initialize struct with search conditions.
|
||||||
|
@ -233,24 +334,24 @@ db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"})
|
||||||
|
|
||||||
### FirstOrInit With Attrs
|
### FirstOrInit With Attrs
|
||||||
|
|
||||||
Attr's arguments would be used to initialize struct if not record found, but won't be used for search
|
Attr's arguments would be used to initialize struct if no record found, but won't be used for search
|
||||||
|
|
||||||
```go
|
```go
|
||||||
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
|
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
|
||||||
//// SELECT * FROM USERS WHERE name = 'non_existing';
|
//// SELECT * FROM USERS WHERE name = 'non_existing';
|
||||||
//// User{Name: "non_existing", Age: 20}
|
//// User{Name: "non_existing", Age: 20}
|
||||||
|
|
||||||
// Above code could be simplified if have only one attribute
|
// Above code could be simplified if has only one attribute
|
||||||
db.Where(User{Name: "noexisting_user"}).Attrs("age", 20).FirstOrInit(&user)
|
db.Where(User{Name: "noexisting_user"}).Attrs("age", 20).FirstOrInit(&user)
|
||||||
|
|
||||||
// If record found, Attrs would be ignored
|
// If a record found, Attrs would be just ignored
|
||||||
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user)
|
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user)
|
||||||
//// SELECT * FROM USERS WHERE name = jinzhu';
|
//// SELECT * FROM USERS WHERE name = jinzhu';
|
||||||
//// User{Id: 111, Name: "Jinzhu", Age: 20}
|
//// User{Id: 111, Name: "Jinzhu", Age: 20}
|
||||||
|
|
||||||
### FirstOrInit With Assign
|
### FirstOrInit With Assign
|
||||||
|
|
||||||
Assign's arguments would be used to set the struct even record found, but won't be used for search
|
Assign's arguments would be used to set the struct even a record found, but won't be used for search
|
||||||
|
|
||||||
```go
|
```go
|
||||||
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
|
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
|
||||||
|
@ -272,21 +373,20 @@ db.Where(User{Name: "Jinzhu"}).FirstOrCreate(&user)
|
||||||
//// User{Id: 111, Name: "Jinzhu"}
|
//// User{Id: 111, Name: "Jinzhu"}
|
||||||
|
|
||||||
db.FirstOrCreate(&user, map[string]interface{}{"name": "jinzhu", "age": 30})
|
db.FirstOrCreate(&user, map[string]interface{}{"name": "jinzhu", "age": 30})
|
||||||
//// user -> User{Id: 111, Name: "Jinzhu", Age: 20}
|
//// user -> User{Id: 111, Name: "jinzhu", Age: 20}
|
||||||
```
|
```
|
||||||
|
|
||||||
### FirstOrCreate With Attrs
|
### FirstOrCreate With Attrs
|
||||||
|
|
||||||
Attr's arguments would be used to initialize struct if not record found, but won't be used for search
|
Attr's arguments would be used to initialize struct if no record found, but won't be used for search
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// FirstOrCreate With Attrs
|
|
||||||
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
|
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
|
||||||
//// SELECT * FROM users WHERE name = 'non_existing';
|
//// SELECT * FROM users WHERE name = 'non_existing';
|
||||||
//// User{Id: 112, Name: "non_existing", Age: 20}
|
//// User{Id: 112, Name: "non_existing", Age: 20}
|
||||||
|
|
||||||
db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)
|
db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)
|
||||||
//// User{Id: 111, Name: "Jinzhu", Age: 20}
|
//// User{Id: 111, Name: "jinzhu", Age: 20}
|
||||||
```
|
```
|
||||||
|
|
||||||
### FirstOrCreate With Assign
|
### FirstOrCreate With Assign
|
||||||
|
@ -298,192 +398,179 @@ If any record found, will assign those values to the record, and save it back to
|
||||||
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
|
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
|
||||||
//// user -> User{Id: 112, Name: "non_existing", Age: 20}
|
//// user -> User{Id: 112, Name: "non_existing", Age: 20}
|
||||||
|
|
||||||
db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrCreate(&user)
|
db.Where(User{Name: "jinzhu"}).Assign(User{Age: 30}).FirstOrCreate(&user)
|
||||||
|
//// SELECT * FROM users WHERE name = 'jinzhu';
|
||||||
//// UPDATE users SET age=30 WHERE id = 111;
|
//// UPDATE users SET age=30 WHERE id = 111;
|
||||||
//// User{Id: 111, Name: "Jinzhu", Age: 30}
|
//// User{Id: 111, Name: "jinzhu", Age: 30}
|
||||||
```
|
```
|
||||||
|
|
||||||
### SELECT
|
## Select
|
||||||
|
|
||||||
```go
|
```go
|
||||||
//// user -> User{Id: 111, Name: "Jinzhu", Age: 18}
|
db.Select("name, age").Find(&users)
|
||||||
//// You must noticed that the Attrs is similar to FirstOrInit with Attrs, yes?
|
//// SELECT name, age FROM users;
|
||||||
|
```
|
||||||
|
|
||||||
// Select
|
## Order
|
||||||
db.Select("name").Find(&users)
|
|
||||||
//// users -> select name from users;
|
|
||||||
|
|
||||||
// Order
|
```go
|
||||||
db.Order("age desc, name").Find(&users)
|
db.Order("age desc, name").Find(&users)
|
||||||
//// users -> select * from users order by age desc, name;
|
//// SELECT * FROM users ORDER BY age desc, name;
|
||||||
|
|
||||||
db.Order("age desc").Order("name").Find(&users)
|
db.Order("age desc").Order("name").Find(&users)
|
||||||
//// users -> select * from users order by age desc, name;
|
//// SELECT * FROM users ORDER BY age desc, name;
|
||||||
|
|
||||||
// ReOrder
|
// ReOrder
|
||||||
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
|
db.Order("age desc").Find(&users1).Order("age", true).Find(&users2)
|
||||||
//// users1 -> select * from users order by age desc;
|
//// SELECT * FROM users ORDER BY age desc; (users1)
|
||||||
//// users2 -> select * from users order by age;
|
//// SELECT * FROM users ORDER BY age; (users2)
|
||||||
|
```
|
||||||
|
|
||||||
// Limit
|
## Limit
|
||||||
|
|
||||||
|
```go
|
||||||
db.Limit(3).Find(&users)
|
db.Limit(3).Find(&users)
|
||||||
//// users -> select * from users limit 3;
|
//// SELECT * FROM users LIMIT 3;
|
||||||
db.Limit(10).Find(&users1).Limit(20).Find(&users2).Limit(-1).Find(&users3)
|
|
||||||
//// users1 -> select * from users limit 10;
|
|
||||||
//// users2 -> select * from users limit 20;
|
|
||||||
//// users3 -> select * from users;
|
|
||||||
|
|
||||||
// Offset
|
// Cleanup limit with -1
|
||||||
//// select * from users offset 3;
|
db.Limit(10).Find(&users1).Limit(-1).Find(&users2)
|
||||||
|
//// SELECT * FROM users LIMIT 10; (users1)
|
||||||
|
//// SELECT * FROM users; (users2)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Offset
|
||||||
|
|
||||||
|
```go
|
||||||
db.Offset(3).Find(&users)
|
db.Offset(3).Find(&users)
|
||||||
db.Offset(10).Find(&users1).Offset(20).Find(&users2).Offset(-1).Find(&users3)
|
//// SELECT * FROM users OFFSET 3;
|
||||||
//// user1 -> select * from users offset 10;
|
|
||||||
//// user2 -> select * from users offset 20;
|
|
||||||
//// user3 -> select * from users;
|
|
||||||
|
|
||||||
// Or
|
// Cleanup offset with -1
|
||||||
db.Where("role = ?", "admin").Or("role = ?", "super_admin").Find(&users)
|
db.Offset(10).Find(&users1).Offset(-1).Find(&users2)
|
||||||
//// users -> select * from users where role = 'admin' or role = 'super_admin';
|
//// SELECT * FROM users OFFSET 10; (users1)
|
||||||
|
//// SELECT * FROM users; (users2)
|
||||||
|
```
|
||||||
|
|
||||||
// Count
|
## Count
|
||||||
|
|
||||||
|
```go
|
||||||
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)
|
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)
|
||||||
//// users -> select * from users where name = 'jinzhu' or name = 'jinzhu 2';
|
//// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users)
|
||||||
//// count -> select count(*) from users where name = 'jinzhu' or name = 'jinzhu 2';
|
//// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)
|
||||||
db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
|
|
||||||
|
|
||||||
// CreatedAt (auto insert current time on create)
|
// Set table name with Model
|
||||||
If your struct has field CreatedAt,
|
db.Model(User{}).Where("name = ?", "jinzhu").Count(&count)
|
||||||
it will be filled with the current time when insert into database
|
//// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)
|
||||||
|
|
||||||
// UpdatedAt (auto update the time on save)
|
// Set table name with Table
|
||||||
If your struct has field UpdatedAt,
|
db.Table("deleted_users").Count(&count)
|
||||||
it will be filled with the current time when update it
|
//// SELECT count(*) FROM deleted_users;
|
||||||
|
```
|
||||||
|
|
||||||
// Callbacks
|
## Pluck
|
||||||
Below callbacks are defined now:
|
|
||||||
|
|
||||||
`BeforeCreate`, `BeforeUpdate`, `BeforeSave`, `AfterCreate`, `AfterUpdate`, `AfterSave`
|
Get struct's attribute as map
|
||||||
|
|
||||||
|
```go
|
||||||
|
var ages []int64
|
||||||
|
db.Find(&users).Pluck("age", &ages)
|
||||||
|
|
||||||
|
// Set Table With Model
|
||||||
|
var names []string
|
||||||
|
db.Model(&User{}).Pluck("name", &names)
|
||||||
|
//// SELECT name FROM users;
|
||||||
|
|
||||||
|
// Set Table With Table
|
||||||
|
db.Table("deleted_users").Pluck("name", &names)
|
||||||
|
//// SELECT name FROM deleted_users;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Callbacks
|
||||||
|
|
||||||
|
Callback is a function defined to a struct, the function would be run when reflect a struct to database.
|
||||||
|
If the function return an error, will prevent following operations. (for example, stop inserting, updating)
|
||||||
|
|
||||||
|
Those callbacks are defined now:
|
||||||
|
|
||||||
|
`BeforeCreate`, `AfterCreate`
|
||||||
|
`BeforeUpdate`, `AfterUpdate`
|
||||||
|
`BeforeSave`, `AfterSave`
|
||||||
`BeforeDelete`, `AfterDelete`
|
`BeforeDelete`, `AfterDelete`
|
||||||
|
|
||||||
Callbacks is a function defined to a model, if the function return error, will prevent the database operations.
|
```go
|
||||||
|
|
||||||
func (u *User) BeforeUpdate() (err error) {
|
func (u *User) BeforeUpdate() (err error) {
|
||||||
if u.readonly() {
|
if u.readonly() {
|
||||||
err = errors.New("Read Only User")
|
err = errors.New("Read Only User")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
|
||||||
// Pluck (get users's age as map)
|
## Specify Table Name
|
||||||
var ages []int64
|
|
||||||
db.Find(&users).Pluck("age", &ages)
|
|
||||||
//// ages -> select age from users;
|
|
||||||
var names []string
|
|
||||||
db.Model(&User{}).Pluck("name", &names)
|
|
||||||
//// names -> select name from users;
|
|
||||||
|
|
||||||
// Query Chains
|
```
|
||||||
db.Where("name <> ?", "jinzhu").Where("age >= ? and role <> ?", 20, "admin").Find(&users)
|
// When Create Table from struct
|
||||||
//// users -> select * from users where name <> 'jinzhu' andd age >= 20 and role <> 'admin';
|
|
||||||
|
|
||||||
// Create Table with struct
|
|
||||||
db.CreateTable(&User{})
|
|
||||||
|
|
||||||
// Drop Table
|
|
||||||
db.DropTable(&User{})
|
|
||||||
|
|
||||||
// Specify Table Name
|
|
||||||
db.Table("deleted_users").CreateTable(&User{})
|
db.Table("deleted_users").CreateTable(&User{})
|
||||||
|
|
||||||
|
// When Pluck
|
||||||
db.Table("users").Pluck("age", &ages)
|
db.Table("users").Pluck("age", &ages)
|
||||||
//// ages -> select age from users;
|
//// SELECT age FROM users;
|
||||||
|
|
||||||
|
// When Query
|
||||||
var deleted_users []User
|
var deleted_users []User
|
||||||
db.Table("deleted_users").Find(&deleted_users)
|
db.Table("deleted_users").Find(&deleted_users)
|
||||||
//// deleted_users -> select * from deleted_users;
|
//// SELECT * FROM deleted_users;
|
||||||
db.Table("deleted_users").Find(&deleted_user)
|
|
||||||
//// deleted_user -> select * from deleted_users limit 1;
|
|
||||||
|
|
||||||
// Update
|
// When Delete
|
||||||
db.Table("users").Where(10).Update("name", "hello")
|
db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
|
||||||
//// update users set name='hello' where id = 10;
|
//// DELETE FROM deleted_users WHERE name = 'jinzhu';
|
||||||
db.Table("users").Update("name", "hello")
|
```
|
||||||
//// update users set name='hello';
|
|
||||||
|
|
||||||
// Updates
|
## Run Raw SQl
|
||||||
db.Table("users").Where(10).Updates(map[string]interface{}{"name": "hello", "age": 18})
|
|
||||||
//// update users set name='hello', age=18 where id = 10;
|
|
||||||
db.Table("users").Updates(map[string]interface{}{"name": "hello", "age": 18})
|
|
||||||
//// update users set name='hello', age=18;
|
|
||||||
db.Find(&users).Updates(User{Name: "hello", Age: 18})
|
|
||||||
//// update users set name='hello', age=18;
|
|
||||||
db.First(&user, 20).Updates(User{Name: "hello", Age: 18})
|
|
||||||
//// update users set name='hello', age=18 where id = 20;
|
|
||||||
//// object user's value would be reflected by the Updates also,
|
|
||||||
//// so you don't need to refetch the user from database
|
|
||||||
|
|
||||||
// Soft Delete
|
```go
|
||||||
// For those struct have DeletedAt field, they will get soft delete ability automatically!
|
|
||||||
type Order struct {
|
|
||||||
Id int64
|
|
||||||
Amount int64
|
|
||||||
CreatedAt time.Time
|
|
||||||
UpdatedAt time.Time
|
|
||||||
DeletedAt time.Time
|
|
||||||
}
|
|
||||||
order := order{Id:10}
|
|
||||||
db.Delete(&order)
|
|
||||||
//// UPDATE orders SET deleted_at="2013-10-29 10:23" WHERE id = 10;
|
|
||||||
db.Where("amount = ?", 0).Delete(&Order{})
|
|
||||||
//// UPDATE orders SET deleted_at="2013-10-29 10:23" WHERE amount = 0;
|
|
||||||
db.Where("amount = 100").Find(&order)
|
|
||||||
//// order -> select * from orders where amount = 100 and (deleted_at is null and deleted_at <= '0001-01-02');
|
|
||||||
// And you are possible to query soft deleted orders with Unscoped method
|
|
||||||
db.Unscoped().Where("amount = 100").Find(&order)
|
|
||||||
//// order -> select * from orders where amount = 100;
|
|
||||||
// Of course, you could permanently delete a record with Unscoped
|
|
||||||
db.Unscoped().Delete(&order)
|
|
||||||
// DELETE from orders where id=10;
|
|
||||||
|
|
||||||
// Run Raw SQL
|
|
||||||
db.Exec("drop table users;")
|
db.Exec("drop table users;")
|
||||||
|
```
|
||||||
|
|
||||||
// Error Handling
|
## Error Handling
|
||||||
|
|
||||||
|
```go
|
||||||
query := db.Where("name = ?", "jinzhu").First(&user)
|
query := db.Where("name = ?", "jinzhu").First(&user)
|
||||||
query := db.First(&user).Limit(10).Find(&users)
|
query := db.First(&user).Limit(10).Find(&users)
|
||||||
//// query.Error -> the last error happened
|
//// query.Error keep the latest error happened
|
||||||
//// query.Errors -> all errors happened
|
//// query.Errors keep all errors happened
|
||||||
//// If an error happened, gorm will stop do insert, update, delete operations
|
//// If an error happened, gorm will stop do query, insert, update, delete
|
||||||
|
|
||||||
|
// I often use below code to do error handling in real applicatoins
|
||||||
|
err = db.Where("name = ?", "jinzhu").First(&user).Error
|
||||||
```
|
```
|
||||||
|
|
||||||
## Advanced Usage With Query Chain
|
## Advanced Usage With Query Chain
|
||||||
|
|
||||||
|
Already excited about above usage? Let's see some magic!
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Already excited about the basic usage? Let's see some magic!
|
|
||||||
|
|
||||||
db.First(&first_article).Count(&total_count).Limit(10).Find(&first_page_articles).Offset(10).Find(&second_page_articles)
|
db.First(&first_article).Count(&total_count).Limit(10).Find(&first_page_articles).Offset(10).Find(&second_page_articles)
|
||||||
//// first_article -> select * from articles limit 1
|
//// SELECT * FROM articles LIMIT 1; (first_article)
|
||||||
//// total_count -> select count(*) from articles
|
//// SELECT count(*) FROM articles; (count)
|
||||||
//// first_page_articles -> select * from articles limit 10
|
//// SELECT * FROM articles LIMIT 10; (first_page_articles)
|
||||||
//// second_page_articles -> select * from articles limit 10 offset 10
|
//// SELECT * FROM articles LIMIT 10 OFFSET 10; (second_page_articles)
|
||||||
|
|
||||||
db.Where("created_at > ?", "2013/10/10").Find(&cancelled_orders, "state = ?", "cancelled").Find(&shipped_orders, "state = ?", "shipped")
|
db.Where("created_at > ?", "2013-10-10").Find(&cancelled_orders, "state = ?", "cancelled").Find(&shipped_orders, "state = ?", "shipped")
|
||||||
//// cancelled_orders -> select * from orders where created_at > '2013/10/10' and state = 'cancelled'
|
//// SELECT * FROM orders WHERE created_at > '2013/10/10' AND state = 'cancelled'; (cancelled_orders)
|
||||||
//// shipped_orders -> select * from orders where created_at > '2013/10/10' and state = 'shipped'
|
//// SELECT * FROM orders WHERE created_at > '2013/10/10' AND state = 'shipped'; (shipped_orders)
|
||||||
|
|
||||||
db.Model(&Order{}).Where("amount > ?", 10000).Pluck("user_id", &paid_user_ids)
|
db.Where("product_name = ?", "fancy_product").Find(&orders).Find(&shopping_carts)
|
||||||
//// paid_user_ids -> select user_id from orders where amount > 10000
|
//// SELECT * FROM orders WHERE product_name = 'fancy_product'; (orders)
|
||||||
db.Where("user_id = ?", paid_user_ids).Find(&:paid_users)
|
//// SELECT * FROM carts WHERE product_name = 'fancy_product'; (shopping_carts)
|
||||||
//// paid_users -> select * from users where user_id in (10, 20, 99)
|
// Do you noticed the table is different?
|
||||||
|
|
||||||
db.Where("product_name = ?", "fancy_product").Find(&orders).Find(&shopping_cart)
|
|
||||||
//// orders -> select * from orders where product_name = 'fancy_product'
|
|
||||||
//// shopping_cart -> select * from carts where product_name = 'fancy_product'
|
|
||||||
// Do you noticed the search table is different for above query, yay
|
|
||||||
|
|
||||||
db.Where("mail_type = ?", "TEXT").Find(&users1).Table("deleted_users").First(&user2)
|
db.Where("mail_type = ?", "TEXT").Find(&users1).Table("deleted_users").First(&user2)
|
||||||
//// users1 -> select * from users where mail_type = 'TEXT';
|
//// SELECT * FROM users WHERE mail_type = 'TEXT'; (users1)
|
||||||
//// users2 -> select * from deleted_users where mail_type = 'TEXT';
|
//// SELECT * FROM deleted_users WHERE mail_type = 'TEXT'; (users2)
|
||||||
|
|
||||||
db.Where("email = ?", "x@example.org"').Attrs(User{FromIp: "111.111.111.111"}).FirstOrCreate(&user)
|
db.Where("email = ?", "x@example.org"').Attrs(User{FromIp: "111.111.111.111"}).FirstOrCreate(&user)
|
||||||
//// user -> select * from users where email = 'x@example.org'
|
//// SELECT * FROM users WHERE email = 'x@example.org';
|
||||||
//// (if no record found) -> INSERT INTO "users" (email,from_ip) VALUES ("x@example.org", "111.111.111.111")
|
//// INSERT INTO "users" (email,from_ip) VALUES ("x@example.org", "111.111.111.111") (if no record found)
|
||||||
|
|
||||||
// Open your mind, add more cool examples
|
// Open your mind, add more cool examples
|
||||||
```
|
```
|
||||||
|
@ -497,7 +584,7 @@ db.Where("email = ?", "x@example.org"').Attrs(User{FromIp: "111.111.111.111"}).F
|
||||||
|
|
||||||
# Author
|
# Author
|
||||||
|
|
||||||
**Jinzhu**
|
**jinzhu**
|
||||||
|
|
||||||
* <http://github.com/jinzhu>
|
* <http://github.com/jinzhu>
|
||||||
* <wosmvp@gmail.com>
|
* <wosmvp@gmail.com>
|
||||||
|
|
17
gorm_test.go
17
gorm_test.go
|
@ -1095,10 +1095,21 @@ func TestT(t *testing.T) {
|
||||||
db.Save(&user)
|
db.Save(&user)
|
||||||
|
|
||||||
var user2 User
|
var user2 User
|
||||||
db.Where("name in (?)", []string{"1,2"}).First(&user2).Update("name", "hhh")
|
debug("asdsd")
|
||||||
|
db.Where("name in (?)", []string{"1"}).First(&user2)
|
||||||
|
|
||||||
|
debug("aaadsd")
|
||||||
debug(user2)
|
debug(user2)
|
||||||
|
db.Model(&user2).Updates(User{Name: "lala", Age: 10})
|
||||||
|
debug("aals")
|
||||||
|
//// UPDATE users SET name='hello' WHERE id=111;
|
||||||
|
|
||||||
var users []User
|
var users []User
|
||||||
db.Find(&users, User{Age: 20})
|
// db.Where("name = '3'").Or(User{Name: "2"}).Find(&users)
|
||||||
debug(users)
|
db.Where("name = '3'").Or(map[string]interface{}{"name": "2"}).Find(&users)
|
||||||
|
var count int64
|
||||||
|
db.Model(User{}).Where("name = ?", "jinzhu").Count(&count)
|
||||||
|
db.Table("users").Count(&count)
|
||||||
|
debug(count)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue