mirror of https://github.com/go-gorm/gorm.git
Create Indexes with AutoMigrate
This commit is contained in:
parent
42f934d60e
commit
6fed43162f
88
README.md
88
README.md
|
@ -35,7 +35,7 @@ type User struct {
|
|||
ID int
|
||||
Birthday time.Time
|
||||
Age int
|
||||
Name string `sql:"size:255"`
|
||||
Name string `sql:"size:255"` // Default size for string is 255, you could reset it with this tag
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
DeletedAt time.Time
|
||||
|
@ -51,8 +51,8 @@ type User struct {
|
|||
|
||||
type Email struct {
|
||||
ID int
|
||||
UserID int // Foreign key for User (belongs to)
|
||||
Email string `sql:"type:varchar(100);"` // Set field's type
|
||||
UserID int `sql:"index"` // Foreign key (belongs to), tag `index` will create index for this field when using AutoMigrate
|
||||
Email string `sql:"type:varchar(100);unique_index"` // Set field's sql type, tag `unique_index` will create unique index
|
||||
Subscribed bool
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,8 @@ type Address struct {
|
|||
|
||||
type Language struct {
|
||||
ID int
|
||||
Name string
|
||||
Name string `sql:"index:idx_name_code"` // Create index with name, and will create combined index if find other fields defined same name
|
||||
Code string `sql:"index:idx_name_code"` // `unique_index` also works
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -74,13 +75,7 @@ type Language struct {
|
|||
* Table name is the plural of struct name's snake case, you can disable pluralization with `db.SingularTable(true)`, or [Specifying The Table Name For A Struct Permanently With TableName](#specifying-the-table-name-for-a-struct-permanently-with-tablename)
|
||||
|
||||
```go
|
||||
// E.g finding an existing User
|
||||
var user User
|
||||
// Gorm will know to use table "users" ("user" if pluralisation has been disabled) for all operations.
|
||||
db.First(&user)
|
||||
|
||||
// creating a new User
|
||||
db.Save(&User{Name: "xxx"}) // table "users"
|
||||
type User struct{} // struct User's database table name is "users" by default, will be "user" if you disabled pluralisation
|
||||
```
|
||||
|
||||
* Column name is the snake case of field's name
|
||||
|
@ -92,7 +87,6 @@ db.Save(&User{Name: "xxx"}) // table "users"
|
|||
## Initialize Database
|
||||
|
||||
```go
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/lib/pq"
|
||||
|
@ -101,7 +95,7 @@ import (
|
|||
)
|
||||
|
||||
db, err := gorm.Open("postgres", "user=gorm dbname=gorm sslmode=disable")
|
||||
// db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True")
|
||||
// db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
|
||||
// db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
|
||||
|
||||
// You can also use an existing database connection handle
|
||||
|
@ -129,38 +123,13 @@ db.CreateTable(&User{})
|
|||
// Drop table
|
||||
db.DropTable(&User{})
|
||||
|
||||
// Drop table if exists
|
||||
db.DropTableIfExists(&User{})
|
||||
|
||||
// Automating Migration
|
||||
db.AutoMigrate(&User{})
|
||||
db.AutoMigrate(&User{}, &Product{}, &Order{})
|
||||
|
||||
// Feel free to change your struct, AutoMigrate will keep your database up-to-date.
|
||||
// Fyi, AutoMigrate will only *add new columns*, it won't update column's type or delete unused columns, to make sure your data is safe.
|
||||
// AutoMigrate will ONLY add *new columns* and *new indexes*,
|
||||
// WON'T update current column's type or delete unused columns, to protect your data.
|
||||
// If the table is not existing, AutoMigrate will create the table automatically.
|
||||
|
||||
// Add index
|
||||
db.Model(&User{}).AddIndex("idx_user_name", "name")
|
||||
|
||||
// Add foreign key
|
||||
// 1st param : foreignkey field
|
||||
// 2nd param : destination table(id)
|
||||
// 3rd param : ONDELETE
|
||||
// 4th param : ONUPDATE
|
||||
db.Model(&User{}).AddForeignKey("user_id", "destination_table(id)", "CASCADE", "RESTRICT")
|
||||
|
||||
// Multiple column index
|
||||
db.Model(&User{}).AddIndex("idx_user_name_age", "name", "age")
|
||||
|
||||
// Add unique index
|
||||
db.Model(&User{}).AddUniqueIndex("idx_user_name", "name")
|
||||
|
||||
// Multiple column unique index
|
||||
db.Model(&User{}).AddUniqueIndex("idx_user_name_age", "name", "age")
|
||||
|
||||
// Remove index
|
||||
db.Model(&User{}).RemoveIndex("idx_user_name")
|
||||
```
|
||||
|
||||
# Basic CRUD
|
||||
|
@ -170,18 +139,13 @@ db.Model(&User{}).RemoveIndex("idx_user_name")
|
|||
```go
|
||||
user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()}
|
||||
|
||||
// returns true if record hasn’t been saved (primary key `Id` is blank)
|
||||
db.NewRecord(user) // => true
|
||||
db.NewRecord(user) // => returns `true` if primary key is blank
|
||||
|
||||
db.Create(&user)
|
||||
|
||||
// will return false after `user` created
|
||||
db.NewRecord(user) // => false
|
||||
db.NewRecord(user) // => return `false` after `user` created
|
||||
|
||||
// You could use `Save` to create record also if its primary key is null
|
||||
db.Save(&user)
|
||||
|
||||
// Associations will be saved automatically when insert the record
|
||||
// Associations will be inserted automatically when save the record
|
||||
user := User{
|
||||
Name: "jinzhu",
|
||||
BillingAddress: Address{Address1: "Billing Address - Address 1"},
|
||||
|
@ -204,7 +168,7 @@ db.Create(&user)
|
|||
//// COMMIT;
|
||||
```
|
||||
|
||||
Refer [Associations](#associations) for how to work with associations
|
||||
Refer [Associations](#associations) for more details
|
||||
|
||||
## Query
|
||||
|
||||
|
@ -1095,6 +1059,32 @@ INSERT INTO animals("age") values('99');
|
|||
|
||||
The same thing occurs in update statements.
|
||||
|
||||
## Database Indexes & Foreign Key
|
||||
|
||||
```go
|
||||
// Add foreign key
|
||||
// 1st param : foreignkey field
|
||||
// 2nd param : destination table(id)
|
||||
// 3rd param : ONDELETE
|
||||
// 4th param : ONUPDATE
|
||||
db.Model(&User{}).AddForeignKey("user_id", "destination_table(id)", "CASCADE", "RESTRICT")
|
||||
|
||||
// Add index
|
||||
db.Model(&User{}).AddIndex("idx_user_name", "name")
|
||||
|
||||
// Multiple column index
|
||||
db.Model(&User{}).AddIndex("idx_user_name_age", "name", "age")
|
||||
|
||||
// Add unique index
|
||||
db.Model(&User{}).AddUniqueIndex("idx_user_name", "name")
|
||||
|
||||
// Multiple column unique index
|
||||
db.Model(&User{}).AddUniqueIndex("idx_user_name_age", "name", "age")
|
||||
|
||||
// Remove index
|
||||
db.Model(&User{}).RemoveIndex("idx_user_name")
|
||||
```
|
||||
|
||||
## More examples with query chain
|
||||
|
||||
```go
|
||||
|
|
|
@ -87,9 +87,9 @@ func TestIndexes(t *testing.T) {
|
|||
type BigEmail struct {
|
||||
Id int64
|
||||
UserId int64
|
||||
Email string
|
||||
UserAgent string
|
||||
RegisteredAt time.Time
|
||||
Email string `sql:"index:idx_email_agent"`
|
||||
UserAgent string `sql:"index:idx_email_agent"`
|
||||
RegisteredAt time.Time `sql:"unique_index"`
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
@ -106,6 +106,15 @@ func TestAutoMigration(t *testing.T) {
|
|||
|
||||
DB.Save(&BigEmail{Email: "jinzhu@example.org", UserAgent: "pc", RegisteredAt: time.Now()})
|
||||
|
||||
scope := DB.NewScope(&BigEmail{})
|
||||
if !scope.Dialect().HasIndex(scope, scope.TableName(), "idx_email_agent") {
|
||||
t.Errorf("Failed to create index")
|
||||
}
|
||||
|
||||
if !scope.Dialect().HasIndex(scope, scope.TableName(), "uix_emails_registered_at") {
|
||||
t.Errorf("Failed to create index")
|
||||
}
|
||||
|
||||
var bigemail BigEmail
|
||||
DB.First(&bigemail, "user_agent = ?", "pc")
|
||||
if bigemail.Email != "jinzhu@example.org" || bigemail.UserAgent != "pc" || bigemail.RegisteredAt.IsZero() {
|
||||
|
|
|
@ -532,5 +532,43 @@ func (scope *Scope) autoMigrate() *Scope {
|
|||
scope.createJoinTable(field)
|
||||
}
|
||||
}
|
||||
|
||||
scope.autoIndex()
|
||||
return scope
|
||||
}
|
||||
|
||||
func (scope *Scope) autoIndex() *Scope {
|
||||
var indexes = map[string][]string{}
|
||||
var uniqueIndexes = map[string][]string{}
|
||||
|
||||
for _, field := range scope.GetStructFields() {
|
||||
sqlSettings := parseTagSetting(field.Tag.Get("sql"))
|
||||
if name, ok := sqlSettings["INDEX"]; ok {
|
||||
if name == "INDEX" {
|
||||
name = fmt.Sprintf("idx_%v_%v", scope.TableName(), field.DBName)
|
||||
}
|
||||
indexes[name] = append(indexes[name], field.DBName)
|
||||
}
|
||||
|
||||
if name, ok := sqlSettings["UNIQUE_INDEX"]; ok {
|
||||
if name == "UNIQUE_INDEX" {
|
||||
name = fmt.Sprintf("uix_%v_%v", scope.TableName(), field.DBName)
|
||||
}
|
||||
uniqueIndexes[name] = append(indexes[name], field.DBName)
|
||||
}
|
||||
}
|
||||
|
||||
for name, columns := range indexes {
|
||||
if !scope.Dialect().HasIndex(scope, scope.TableName(), name) {
|
||||
scope.addIndex(false, name, columns...)
|
||||
}
|
||||
}
|
||||
|
||||
for name, columns := range uniqueIndexes {
|
||||
if !scope.Dialect().HasIndex(scope, scope.TableName(), name) {
|
||||
scope.addIndex(true, name, columns...)
|
||||
}
|
||||
}
|
||||
|
||||
return scope
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue