1. 程式人生 > >ent orm筆記2---schema使用(下)

ent orm筆記2---schema使用(下)

## Indexes 索引 在前兩篇的文章中,其實對於索引也有一些使用, 這裡來詳細看一下關於索引的使用 Indexes方法可以在一個或者多個欄位上設定索引,以提高資料檢索的速度或者定義資料的唯一性 在下面這個例子中,對user表的`field1` 和`field2` 欄位設定了聯合索引;對`first_name`和`last_name`設定了聯合唯一索引; 對`field3` 設定了唯一索引。 這裡需要注意對於單獨的欄位設定唯一索引,在Fields中定義欄位的時候通過Unique方法即可 ```go package schema import ( "github.com/facebook/ent" "github.com/facebook/ent/schema/field" "github.com/facebook/ent/schema/index" ) // User holds the schema definition for the User entity. type User struct { ent.Schema } // Fields of the User. func (User) Fields() []ent.Field { return []ent.Field{ field.String("field1"), field.String("field2"), field.String("field3").Unique(), field.String("first_name"), field.String("last_name"), } } // Edges of the User. func (User) Edges() []ent.Edge { return nil } func Indexes() []ent.Index { return []ent.Index{ // non-unique index. index.Fields("field1", "field2"), // unique index index.Fields("first_name", "last_name").Unique(), } } ``` 檢視一下生成的表的資訊: ```sql CREATE TABLE `users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `field1` varchar(255) COLLATE utf8mb4_bin NOT NULL, `field2` varchar(255) COLLATE utf8mb4_bin NOT NULL, `field3` varchar(255) COLLATE utf8mb4_bin NOT NULL, `first_name` varchar(255) COLLATE utf8mb4_bin NOT NULL, `last_name` varchar(255) COLLATE utf8mb4_bin NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `field3` (`field3`), UNIQUE KEY `user_first_name_last_name` (`first_name`,`last_name`), KEY `user_field1_field2` (`field1`,`field2`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ``` ### Index On Edges 在建立表關係的時候也可以對相應的欄位設定索引,主要實在特定關係下設定欄位的唯一性 ![er-city-streets](https://entgo.io/assets/er_city_streets.png) 在這個例子中,我們有一個有許多街道的城市,我們希望在每個城市下設定街道名稱是唯一的。 `ent/schema/city.go` ```go package schema import ( "github.com/facebook/ent" "github.com/facebook/ent/schema/edge" "github.com/facebook/ent/schema/field" ) // City holds the schema definition for the City entity. type City struct { ent.Schema } // Fields of the City. func (City) Fields() []ent.Field { return []ent.Field{ field.String("name"), } } // Edges of the City. func (City) Edges() []ent.Edge { return []ent.Edge{ edge.To("streets", Street.Type), } } ``` `ent/schema/street.go` ```go package schema import ( "github.com/facebook/ent" "github.com/facebook/ent/schema/edge" "github.com/facebook/ent/schema/field" ) // Street holds the schema definition for the Street entity. type Street struct { ent.Schema } // Fields of the Street. func (Street) Fields() []ent.Field { return []ent.Field{ field.String("name"), } } // Edges of the Street. func (Street) Edges() []ent.Edge { return []ent.Edge{ edge.From("city", City.Type). Ref("streets"). Unique(), } } ``` 在上一篇文章中這種用法我們已經見過,我們看一下這樣建立的表資訊,主要是看streets這個表: ```sql CREATE TABLE `streets` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_bin NOT NULL, `city_streets` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), KEY `streets_cities_streets` (`city_streets`), CONSTRAINT `streets_cities_streets` FOREIGN KEY (`city_streets`) REFERENCES `cities` (`id`) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ``` 在`ent/schema/street.go` 新增索引的資訊後,再次檢視streets表的資訊,其實這裡我們就是通過新增約束,使得一個城市中每個街道的名稱是唯一的 ```go func (Street) Indexes() []ent.Index { return []ent.Index{ index.Fields("name"). Edges("city"). Unique(), } } ``` ```sql CREATE TABLE `streets` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) COLLATE utf8mb4_bin NOT NULL, `city_streets` bigint(20) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `street_name_city_streets` (`name`,`city_streets`), KEY `streets_cities_streets` (`city_streets`), CONSTRAINT `streets_cities_streets` FOREIGN KEY (`city_streets`) REFERENCES `cities` (`id`) ON DELETE SET NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ``` ## Config 可以使用Table選項為型別提供自定義表名,如下所示: ```go package schema import ( "github.com/facebook/ent" "github.com/facebook/ent/schema/field" ) type User struct { ent.Schema } func (User) Config() ent.Config { return ent.Config{ Table: "Users", } } func (User) Fields() []ent.Field { return []ent.Field{ field.Int("age"), field.String("name"), } } ``` ## Mixin Mixin允許您建立可重用的`ent.Schema`程式碼。`ent.Mixin` 介面如下: ```go Mixin interface { // Fields returns a slice of fields to add to the schema. Fields() []Field // Edges returns a slice of edges to add to the schema. Edges() []Edge // Indexes returns a slice of indexes to add to the schema. Indexes() []Index // Hooks returns a slice of hooks to add to the schema. // Note that mixin hooks are executed before schema hooks. Hooks() []Hook } ``` Mixin的一個常見用例是將一些常用的通用欄位進行內建,如下: ```go package schema import ( "time" "github.com/facebook/ent" "github.com/facebook/ent/schema/field" "github.com/facebook/ent/schema/mixin" ) // ------------------------------------------------- // Mixin definition // TimeMixin implements the ent.Mixin for sharing // time fields with package schemas. type TimeMixin struct{ // We embed the `mixin.Schema` to avoid // implementing the rest of the methods. mixin.Schema } func (TimeMixin) Fields() []ent.Field { return []ent.Field{ field.Time("created_at"). Immutable(). Default(time.Now), field.Time("updated_at"). Default(time.Now). UpdateDefault(time.Now), } } // DetailsMixin implements the ent.Mixin for sharing // entity details fields with package schemas. type DetailsMixin struct{ // We embed the `mixin.Schema` to avoid // implementing the rest of the methods. mixin.Schema } func (DetailsMixin) Fields() []ent.Field { return []ent.Field{ field.Int("age"). Positive(), field.String("name"). NotEmpty(), } } // ------------------------------------------------- // Schema definition // User schema mixed-in the TimeMixin and DetailsMixin fields and therefore // has 5 fields: `created_at`, `updated_at`, `age`, `name` and `nickname`. type User struct { ent.Schema } func (User) Mixin() []ent.Mixin { return []ent.Mixin{ TimeMixin{}, DetailsMixin{}, } } func (User) Fields() []ent.Field { return []ent.Field{ field.String("nickname"). Unique(), } } // Pet schema mixed-in the DetailsMixin fields and therefore // has 3 fields: `age`, `name` and `weight`. type Pet struct { ent.Schema } func (Pet) Mixin() []ent.Mixin { return []ent.Mixin{ DetailsMixin{}, } } func (Pet) Fields() []ent.Field { return []ent.Field{ field.Float("weight"), } } ``` ### Builtin Mixin `Mixin`提供了一些內建的`Mixin`,可用於將create_time和update_time欄位新增到schema中。 為了使用它們,將` mixin.Time mixin` 新增到schema,如下所示: ```go package schema import ( "github.com/facebook/ent" "github.com/facebook/ent/schema/mixin" ) type Pet struct { ent.Schema } func (Pet) Mixin() []ent.Mixin { return []ent.Mixin{ mixin.Time{}, // Or, mixin.CreateTime only for create_time // and mixin.UpdateTime only for update_time. } } ``` ## 延伸閱讀 - https://e