From 6bc050c2e0442601860e072957b221e4abace891 Mon Sep 17 00:00:00 2001 From: Jinzhu Date: Tue, 8 Mar 2016 09:35:39 +0800 Subject: [PATCH] Update document --- documents/associations.md | 14 +++++++++ documents/curd.md | 62 ++++++++++++++++++++++++++------------- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/documents/associations.md b/documents/associations.md index 59b872df..213c6f6e 100644 --- a/documents/associations.md +++ b/documents/associations.md @@ -174,6 +174,20 @@ db.Model(&user).Related(&languages) //// SELECT * FROM "languages" INNER JOIN "user_languages" ON "user_languages"."language_id" = "languages"."id" WHERE "user_languages"."user_id" = 111 ``` +*Specify Foreign Key & Association Key* + +```go +type CustomizePerson struct { + IdPerson string `gorm:"primary_key:true"` + Accounts []CustomizeAccount `gorm:"many2many:PersonAccount;AssociationForeignKey:idAccount;ForeignKey:idPerson"` +} + +type CustomizeAccount struct { + IdAccount string `gorm:"primary_key:true"` + Name string +} +``` + ## Polymorphism Supports polymorphic has-many and has-one associations. diff --git a/documents/curd.md b/documents/curd.md index 998c1fb9..144cf4eb 100644 --- a/documents/curd.md +++ b/documents/curd.md @@ -40,16 +40,16 @@ db.Create(&user) ### Create With Associations -Refer Associations for more details +Refer [Associations](associations.html) for more details ### Default Values -You could defined default value in the `sql` tag, then the generated creating SQL will ignore these fields that including default value and its value is blank, and after inserted the record into databae, gorm will load those fields's value from database. +You could define default value in the `gorm` tag, then the inserting SQL will ignore these fields that has default value and its value is blank, and after insert the record into databae, gorm will load those fields's value from database. ```go type Animal struct { ID int64 - Name string `sql:"default:'galeone'"` + Name string `gorm:"default:'galeone'"` Age int64 } @@ -62,7 +62,7 @@ db.Create(&animal) ### Setting Primary Key In Callbacks -If you want to set primary key in `BeforeCreate` callback, you could use `scope.SetColumn`, for example: +If you want to set primary field's value in `BeforeCreate` callback, you could use `scope.SetColumn`, for example: ```go func (user *User) BeforeCreate(scope *gorm.Scope) error { @@ -79,15 +79,14 @@ db.Set("gorm:insert_option", "ON CONFLICT").Create(&product) // INSERT INTO products (name, code) VALUES ("name", "code") ON CONFLICT; ``` - ## Query ```go -// Get the first record +// Get first record, order by primary key db.First(&user) //// SELECT * FROM users ORDER BY id LIMIT 1; -// Get the last record +// Get last record, order by primary key db.Last(&user) //// SELECT * FROM users ORDER BY id DESC LIMIT 1; @@ -103,7 +102,7 @@ db.First(&user, 10) ### Query With Where (Plain SQL) ```go -// Get the first matched record +// Get first matched record db.Where("name = ?", "jinzhu").First(&user) //// SELECT * FROM users WHERE name = 'jinzhu' limit 1; @@ -120,7 +119,7 @@ db.Where("name in (?)", []string{"jinzhu", "jinzhu 2"}).Find(&users) db.Where("name LIKE ?", "%jin%").Find(&users) // AND -db.Where("name = ? and age >= ?", "jinzhu", "22").Find(&users) +db.Where("name = ? AND age >= ?", "jinzhu", "22").Find(&users) // Time db.Where("updated_at > ?", lastWeek).Find(&users) @@ -130,6 +129,8 @@ db.Where("created_at BETWEEN ? AND ?", lastWeek, today).Find(&users) ### Query With Where (Struct & Map) +**NOTE** When query with struct, GORM will only query with those fields has value + ```go // Struct db.Where(&User{Name: "jinzhu", Age: 20}).First(&user) @@ -172,6 +173,8 @@ db.Not(User{Name: "jinzhu"}).First(&user) ### Query With Inline Condition +**NOTE** When query with primary key, you should carefully check the value you passed is a valid primary key, to avoid SQL injection + ```go // Get by primary key db.First(&user, 23) @@ -228,7 +231,7 @@ db.Set("gorm:query_option", "FOR UPDATE").First(&user, 10) ### FirstOrInit -Get the first matched record, or initialize a record with search conditions. +Get first matched record, or initalize a new one with given conditions (only works with struct, map conditions) ```go // Unfound @@ -244,7 +247,7 @@ db.FirstOrInit(&user, map[string]interface{}{"name": "jinzhu"}) #### Attrs -Ignore some values when searching, but use them to initialize the struct if record is not found. +Initalize struct with argument if record haven't been found ```go // Unfound @@ -264,7 +267,7 @@ db.Where(User{Name: "Jinzhu"}).Attrs(User{Age: 30}).FirstOrInit(&user) #### Assign -Ignore some values when searching, but assign it to the result regardless it is found or not. +Assign argument to results regardless it is found or not ```go // Unfound @@ -279,7 +282,7 @@ db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrInit(&user) ### FirstOrCreate -Get the first matched record, or create with search conditions. +Get first matched record, or create a new one with given conditions (only works with struct, map conditions) ```go // Unfound @@ -294,7 +297,7 @@ db.Where(User{Name: "Jinzhu"}).FirstOrCreate(&user) #### Attrs -Ignore some values when searching, but use them to create the struct if record is not found. like `FirstOrInit` +Assgin struct with argument if record haven't been found ```go // Unfound @@ -311,7 +314,7 @@ db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user) #### Assign -Ignore some values when searching, but assign it to the record regardless it is found or not, then save back to database. like `FirstOrInit` +Assign it to the record regardless it is found or not, and save back to database. ```go // Unfound @@ -329,6 +332,8 @@ db.Where(User{Name: "jinzhu"}).Assign(User{Age: 30}).FirstOrCreate(&user) ### Select +Specify fields that you want to retrieve from database, by default, will select all fields; + ```go db.Select("name, age").Find(&users) //// SELECT name, age FROM users; @@ -342,6 +347,8 @@ db.Table("users").Select("COALESCE(age,?)", 42).Rows() ### Order +Specify order when retrieve records from database, set reorder to `true` to overwrite defined conditions + ```go db.Order("age desc, name").Find(&users) //// SELECT * FROM users ORDER BY age desc, name; @@ -358,6 +365,8 @@ db.Order("age desc").Find(&users1).Order("age", true).Find(&users2) ### Limit +Specify the number of records to be retrieved + ```go db.Limit(3).Find(&users) //// SELECT * FROM users LIMIT 3; @@ -370,6 +379,8 @@ db.Limit(10).Find(&users1).Limit(-1).Find(&users2) ### Offset +Specify the number of records to skip before starting to return the records + ```go db.Offset(3).Find(&users) //// SELECT * FROM users OFFSET 3; @@ -382,6 +393,8 @@ db.Offset(10).Find(&users1).Offset(-1).Find(&users2) ### Count +Get how many records for a model + ```go db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count) //// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users) @@ -416,6 +429,8 @@ db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Grou ### Joins +Specify Joins conditions + ```go rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows() for rows.Next() { @@ -430,7 +445,7 @@ db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzh ### Pluck -Get selected attributes as map +Query single column from a model as a map ```go var ages []int64 @@ -464,6 +479,8 @@ db.Raw("SELECT name, age FROM users WHERE name = ?", 3).Scan(&result) ### Scopes +Pass current database connection to `func(*DB) *DB`, which could be used to add conditions dynamically + ```go func AmountGreaterThan1000(db *gorm.DB) *gorm.DB { return db.Where("amount > ?", 1000) @@ -536,7 +553,6 @@ db.Model(&user).Update("name", "hello") db.Model(&user).Where("active = ?", true).Update("name", "hello") //// UPDATE users SET name='hello', updated_at='2013-11-17 21:34:10' WHERE id=111 AND active=true; - // Update multiple attributes with `map`, will only update those changed fields db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false}) //// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111; @@ -564,7 +580,7 @@ db.Model(&user).Omit("name").Updates(map[string]interface{}{"name": "hello", "ag ### Update Changed Fields Without Callbacks -Updating operations above will invoke `BeforeUpdate`, `AfterUpdate`, Update UpdatedAt timestamp, Save Associations callbacks, if you don't call them, you could use `UpdateColumn`, `UpdateColumns` +Above updating operations will perform the mdoel's `BeforeUpdate`, `AfterUpdate` method, update its `UpdatedAt` timestamp, save its `Associations` when updaing, if you don't want to call them, you could use `UpdateColumn`, `UpdateColumns` ```go // Update single attribute, similar with `Update` @@ -630,6 +646,8 @@ db.Model(&user).Set("gorm:update_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Updat ## Delete +**WARNING** When delete a record, you need to ensure it's primary field has value, and GORM will use the primary key to delete the record, if primary field's blank, GORM will delete all records for the model + ```go // Delete an existing record db.Delete(&email) @@ -642,15 +660,19 @@ db.Set("gorm:delete_option", "OPTION (OPTIMIZE FOR UNKNOWN)").Delete(&email) ### Batch Delete +Delete all matched records + ```go db.Where("email LIKE ?", "%jinzhu%").Delete(Email{}) //// DELETE from emails where email LIKE "%jinhu%"; + +db.Delete(Email{}, "email LIKE ?", "%jinzhu%") +//// DELETE from emails where email LIKE "%jinhu%"; ``` ### Soft Delete -If struct has `DeletedAt` field, it will get soft delete ability automatically! -Then it won't be deleted from database permanently when call `Delete`. +If model has `DeletedAt` field, it will get soft delete ability automatically! then it won't be deleted from database permanently when call `Delete`, but only set field `DeletedAt`'s value to current time ```go db.Delete(&user)