id: schema-indexes

title: Indexes

复合索引

为了提高数据检索的速度或确保数据的唯一性,可以在一个或多个字段上配置索引。

  1. package schema
  2. import (
  3. "github.com/facebookincubator/ent"
  4. "github.com/facebookincubator/ent/schema/index"
  5. )
  6. // User holds the schema definition for the User entity.
  7. type User struct {
  8. ent.Schema
  9. }
  10. func (User) Indexes() []ent.Index {
  11. return []ent.Index{
  12. // non-unique index.
  13. index.Fields("field1", "field2"),
  14. // unique index.
  15. index.Fields("first_name", "last_name").
  16. Unique(),
  17. }
  18. }

注意,要将单个字段设为唯一索引,请像下面的例子一样在构建器中使用 Unique 方法。

  1. func (User) Fields() []ent.Field {
  2. return []ent.Field{
  3. field.String("phone").
  4. Unique(),
  5. }
  6. }

边的索引

Indexes can be configured on composition of fields and edges. The main use-case is setting uniqueness on fields under a specific relation. Let’s take an example: 可以配置字段和边组成的索引,这主要用于确保某些关系下数据的唯一性。看一个例子:

er-city-streets

In the example above, we have a City with many Streets, and we want to set the street name to be unique under each city. 上面的例子中,一个 City 有多条 Street, 我们想确保街道名在其所属的城市内是唯一的。

ent/schema/city.go

  1. // City holds the schema definition for the City entity.
  2. type City struct {
  3. ent.Schema
  4. }
  5. // Fields of the City.
  6. func (City) Fields() []ent.Field {
  7. return []ent.Field{
  8. field.String("name"),
  9. }
  10. }
  11. // Edges of the City.
  12. func (City) Edges() []ent.Edge {
  13. return []ent.Edge{
  14. edge.To("streets", Street.Type),
  15. }
  16. }

ent/schema/street.go

  1. // Street holds the schema definition for the Street entity.
  2. type Street struct {
  3. ent.Schema
  4. }
  5. // Fields of the Street.
  6. func (Street) Fields() []ent.Field {
  7. return []ent.Field{
  8. field.String("name"),
  9. }
  10. }
  11. // Edges of the Street.
  12. func (Street) Edges() []ent.Edge {
  13. return []ent.Edge{
  14. edge.From("city", City.Type).
  15. Ref("streets").
  16. Unique(),
  17. }
  18. }
  19. // Indexes of the Street.
  20. func (Street) Indexes() []ent.Index {
  21. return []ent.Index{
  22. index.Fields("name").
  23. Edges("city").
  24. Unique(),
  25. }
  26. }

example.go

  1. func Do(ctx context.Context, client *ent.Client) error {
  2. // 不同于 `Save`, `SaveX` 遇到错误是会引起 panics.
  3. tlv := client.City.
  4. Create().
  5. SetName("TLV").
  6. SaveX(ctx)
  7. nyc := client.City.
  8. Create().
  9. SetName("NYC").
  10. SaveX(ctx)
  11. // 将街道 "ST" 添加至城市 "TLV".
  12. client.Street.
  13. Create().
  14. SetName("ST").
  15. SetCity(tlv).
  16. SaveX(ctx)
  17. // 下面的操作会失败,因为城市 "TLV" 已经存在名为 "ST" 街道。
  18. _, err := client.Street.
  19. Create().
  20. SetName("ST").
  21. SetCity(tlv).
  22. Save(ctx)
  23. if err == nil {
  24. return fmt.Errorf("expecting creation to fail")
  25. }
  26. // 将街道 "ST" 添加至城市 "NYC".
  27. client.Street.
  28. Create().
  29. SetName("ST").
  30. SetCity(nyc).
  31. SaveX(ctx)
  32. return nil
  33. }

完整的例子请查看 GitHub.

支持的方言

目前不支持 Gremlin 的索引,只支持 SQL 的索引。