ent orm筆記2---schema使用(下)
阿新 • • 發佈:2020-08-28
## 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