ent 提供了图查询的能力,实际上在关系数据库中的表现就是relation,以下代码接前文

添加边(关系)

  • 添加schema
entc init Car Group

效果:

  • 添加字段
    car
package schema
import (
 "github.com/facebookincubator/ent"
 "github.com/facebookincubator/ent/schema/field"
)
// Car holds the schema definition for the Car entity.
type Car struct {
 ent.Schema
}
// Fields of the Car.
func (Car) Fields() []ent.Field {
 return []ent.Field{
  field.String("model"),
  field.Time("registered_at"),
 }
}
// Edges of the Car.
func (Car) Edges() []ent.Edge {
 return nil
}
 

Group

package schema
import (
 "regexp"
 "github.com/facebookincubator/ent"
 "github.com/facebookincubator/ent/schema/field"
)
// Group holds the schema definition for the Group entity.
type Group struct {
 ent.Schema
}
// Fields of the Group.
func (Group) Fields() []ent.Field {
 return []ent.Field{
  field.String("name").
   // regexp validation for group name.
   Match(regexp.MustCompile("[a-zA-Z_]+$")),
 }
}
// Edges of the Group.
func (Group) Edges() []ent.Edge {
 return nil
}
 
 
  • 定义关系
    以下是一个用户拥有多辆汽车,但是车只能拥有一个所有者

边定义(user schema)

 
package schema
import (
 "github.com/facebookincubator/ent"
 "github.com/facebookincubator/ent/schema/edge"
 "github.com/facebookincubator/ent/schema/field"
)
// 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.Int("age").
   Positive(),
  field.String("name").
   Default("unknown"),
 }
}
// Edges of the User.
func (User) Edges() []ent.Edge {
 return []ent.Edge{
  edge.To("cars", Car.Type),
 }
}
 
 
  • 生成代码
entc generate ./ent/schema
 

效果

  • 创建car 处理

    注意需要运行scheme 迁移 go run cmd/migration/main.go

package main
import (
 "context"
 "fmt"
 "log"
 "time"
 _ "github.com/go-sql-driver/mysql"
 "github.com/rongfengliang/ent-demo/ent"
)
func main() {
 client, err := ent.Open("mysql", "root:dalongrong@tcp(127.0.0.1)/gogs")
 if err != nil {
  log.Fatalf("failed opening connection to sqlite: %v", err)
 }
 defer client.Close()
 ctx := context.Background()
 u, err := createCars(ctx, client)
 if err != nil {
  log.Fatal("some wrong", err)
 } else {
  log.Printf("user %s", u)
 }
}
func createCars(ctx context.Context, client *ent.Client) (*ent.User, error) {
 // creating new car with model "Tesla".
 tesla, err := client.Car.
  Create().
  SetModel("Tesla").
  SetRegisteredAt(time.Now()).
  Save(ctx)
 if err != nil {
  return nil, fmt.Errorf("failed creating car: %v", err)
 }
 // creating new car with model "Ford".
 ford, err := client.Car.
  Create().
  SetModel("Ford").
  SetRegisteredAt(time.Now()).
  Save(ctx)
 if err != nil {
  return nil, fmt.Errorf("failed creating car: %v", err)
 }
 log.Println("car was created: ", ford)
 // create a new user, and add it the 2 cars.
 a8m, err := client.User.
  Create().
  SetAge(30).
  SetName("a8m").
  AddCars(tesla, ford).
  Save(ctx)
 if err != nil {
  return nil, fmt.Errorf("failed creating user: %v", err)
 }
 log.Println("user was created: ", a8m)
 return a8m, nil
}
 
 

运行效果

go run cmd/edge/car/main.go 
2019/10/14 14:26:06 car was created: Car(id=2, model=Ford, registered_at=2019-10-14 14:26:06.869078 +0800 CST m=+0.007888096)
2019/10/14 14:26:06 user was created: User(id=6, age=30, name=a8m)
2019/10/14 14:26:06 user User(id=6, age=30, name=a8m)
  • 生成的ddl
    car
CREATE TABLE `cars` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `model` varchar(255) COLLATE utf8mb4_bin NOT NULL,
  `registered_at` timestamp NULL DEFAULT NULL,
  `user_car_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `cars_users_cars` (`user_car_id`),
  CONSTRAINT `cars_users_cars` FOREIGN KEY (`user_car_id`) REFERENCES `users` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
 
 

ER 模型

  • 查询car
 
func QueryCars(ctx context.Context, a8m *ent.User) error {
    cars, err := a8m.QueryCars().All(ctx)
    if err != nil {
        return fmt.Errorf("failed querying user cars: %v", err)
    }
    log.Println("returned cars:", cars)
    // what about filtering specific cars.
    ford, err := a8m.QueryCars().
        Where(car.ModelEQ("Ford")).
        Only(ctx)
    if err != nil {
        return fmt.Errorf("failed querying user cars: %v", err)
    }
    log.Println(ford)
    return nil
}

添加BackRef

实际上就是上边说的约束,一辆车只能有一个拥有着

  • 给car 对象添加边的约束
 
package schema
import (
    "github.com/facebookincubator/ent"
    "github.com/facebookincubator/ent/schema/edge"
    "github.com/facebookincubator/ent/schema/field"
)
// Car holds the schema definition for the Car entity.
type Car struct {
    ent.Schema
}
// Fields of the Car.
func (Car) Fields() []ent.Field {
    return []ent.Field{
        field.String("model"),
        field.Time("registered_at"),
    }
}
// Edges of the Car.
func (Car) Edges() []ent.Edge {
    return []ent.Edge{
        // create an inverse-edge called "owner" of type `User`
        // and reference it to the "cars" edge (in User schema)
        // explicitly using the `Ref` method.
        edge.From("owner", User.Type).
            Ref("cars").
            // setting the edge to unique, ensure
            // that a car can have only one owner.
            Unique(),
    }
}
  • 生成代码
entc generate ./ent/schema
  • 运行schema 迁移
go run cmd/migration/main.go

效果
ddl

 
CREATE TABLE `cars` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `model` varchar(255) COLLATE utf8mb4_bin NOT NULL,
  `registered_at` timestamp NULL DEFAULT NULL,
  `user_car_id` bigint(20) DEFAULT NULL,
  `owner_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `cars_users_cars` (`user_car_id`),
  CONSTRAINT `cars_users_cars` FOREIGN KEY (`user_car_id`) REFERENCES `users` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
 

  • 查询
    cmd/edge/car/main.go
 
package main
import (
    "context"
    "fmt"
    "log"
    "time"
    _ "github.com/go-sql-driver/mysql"
    "github.com/rongfengliang/ent-demo/ent"
)
func main() {
    client, err := ent.Open("mysql", "root:dalongrong@tcp(127.0.0.1)/gogs")
    if err != nil {
        log.Fatalf("failed opening connection to sqlite: %v", err)
    }
    defer client.Close()
    ctx := context.Background()
    u, err := createCars(ctx, client)
    if err != nil {
        log.Fatal("some wrong", err)
    } else {
        log.Printf("user %s", u)
    }
    QueryCarUsers(ctx, u)
}
func createCars(ctx context.Context, client *ent.Client) (*ent.User, error) {
    // creating new car with model "Tesla".
    tesla, err := client.Car.
        Create().
        SetModel("Tesla").
        SetRegisteredAt(time.Now()).
        Save(ctx)
    if err != nil {
        return nil, fmt.Errorf("failed creating car: %v", err)
    }
    // creating new car with model "Ford".
    ford, err := client.Car.
        Create().
        SetModel("Ford").
        SetRegisteredAt(time.Now()).
        Save(ctx)
    if err != nil {
        return nil, fmt.Errorf("failed creating car: %v", err)
    }
    log.Println("car was created: ", ford)
    // create a new user, and add it the 2 cars.
    a8m, err := client.User.
        Create().
        SetAge(30).
        SetName("a8m").
        AddCars(tesla, ford).
        Save(ctx)
    if err != nil {
        return nil, fmt.Errorf("failed creating user: %v", err)
    }
    log.Println("user was created: ", a8m)
    return a8m, nil
}
func QueryCarUsers(ctx context.Context, a8m *ent.User) error {
    cars, err := a8m.QueryCars().All(ctx)
    if err != nil {
        return fmt.Errorf("failed querying user cars: %v", err)
    }
    // query the inverse edge.
    for _, ca := range cars {
        owner, err := ca.QueryOwner().Only(ctx)
        if err != nil {
            return fmt.Errorf("failed querying car %q owner: %v", ca.Model, err)
        }
        log.Printf("car %q owner: %q\n", ca.Model, owner.Name)
    }
    return nil
}
 
 

效果

go run cmd/edge/car/main.go 
2019/10/14 14:54:08 car was created: Car(id=4, model=Ford, registered_at=2019-10-14 14:54:08.647003 +0800 CST m=+0.007479891)
2019/10/14 14:54:08 user was created: User(id=7, age=30, name=a8m)
2019/10/14 14:54:08 user User(id=7, age=30, name=a8m)
2019/10/14 14:54:08 car "Tesla" owner: "a8m"
2019/10/14 14:54:08 car "Ford" owner: "a8m"
 
 

创建m2m 的关系

需要实现的关系图如下:

  • 添加边的处理
    groups
 
package schema
import (
 "regexp"
 "github.com/facebookincubator/ent"
 "github.com/facebookincubator/ent/schema/edge"
 "github.com/facebookincubator/ent/schema/field"
)
// Group holds the schema definition for the Group entity.
type Group struct {
 ent.Schema
}
// Fields of the Group.
func (Group) Fields() []ent.Field {
 return []ent.Field{
  field.String("name").
   // regexp validation for group name.
   Match(regexp.MustCompile("[a-zA-Z_]+$")),
 }
}
// Edges of the Group.
func (Group) Edges() []ent.Edge {
 return []ent.Edge{
  edge.To("users", User.Type),
 }
}
 
 

users

package schema
import (
 "github.com/facebookincubator/ent"
 "github.com/facebookincubator/ent/schema/edge"
 "github.com/facebookincubator/ent/schema/field"
)
// 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.Int("age").
   Positive(),
  field.String("name").
   Default("unknown"),
 }
}
// Edges of the User.
func (User) Edges() []ent.Edge {
 return []ent.Edge{
  edge.To("cars", Car.Type),
  edge.From("groups", Group.Type).
   Ref("users"),
 }
}
  • 生成代码
entc generate ./ent/schema
  • 运行模式迁移
go run cmd/migration/main.go
 

生成的er 模型,从图中我们可以看出是通过中间表解决m2m的问题,通过ent/migrate/schema.go 代码可以也看出来

说明

以上是一个简单的关系处理的学习,后边会看看图查询的处理

参考资料

https://entgo.io/docs/getting-started/
https://github.com/rongfengliang/ent-demo

ent 基本使用 三 边(关系处理)的更多相关文章

  1. MySQL学习7 - 外键的变种 三种关系

    一 介绍 二 如何找两张表之间的关系 三 表的三种关系 1.书和出版社 2.作者和书籍的关系 3.用户和博客 本节的重点 如何找出两张表之间的关系 表的三种关系 一 介绍 因为有foreign key ...

  2. Mysql -- 外键的变种 三种关系

    一.介绍 因为有foreign  key的约束,  使得两张表形成了三种关系 多对一      多对多   一对一 二.如果找出两张表之间的关系 #.先站在左表的角度去找 是否左表的多条记录可以对应右 ...

  3. python 全栈开发,Day62(外键的变种(三种关系),数据的增删改,单表查询,多表查询)

    一.外键的变种(三种关系) 本节重点: 如何找出两张表之间的关系 表的三种关系 一.介绍 因为有foreign key的约束,使得两张表形成了三种了关系: 多对一 多对多 一对一 二.重点理解如果找出 ...

  4. day05-表的三种关系

    表的三种关系 1)一对一 关联方式:foreign key+unique例如1个学生只能有1个学号,1个学号只能对应1个学生 #两张表: 学生表(student)和 学号表(student_id) # ...

  5. 完整性约束&外键变种三种关系&数据的增删改

    完整性约束 本节重点: not null 与 default unique primary auto_increment foreign key 一.介绍 约束条件与数据类型的宽度一样,都是可选参数 ...

  6. mysql更新(五) 完整性约束 外键的变种 三种关系 数据的增删改

    11-数据的增删改   本节重点: 插入数据 INSERT 更新数据 UPDATE 删除数据 DELETE 再来回顾一下之前我们练过的一些操作,相信大家都对插入数据.更新数据.删除数据有了全面的认识. ...

  7. mysq表的三种关系,数据的增删改以及单表多表查询

    一丶三种关系 分析步骤: #.先站在左表的角度去找 是否左表的多条记录可以对应右表的一条记录,如果是,则证明左表的一个字段foreign key 右表一个字段(通常是id) #.再站在右表的角度去找 ...

  8. (转)Hibernate关联映射——对象的三种关系

    http://blog.csdn.net/yerenyuan_pku/article/details/70148618 Hibernate关联映射——对象的三种关系 Hibernate框架基于ORM设 ...

  9. Mysql外键的变种 三种关系

    一.介绍 因为有foreign key的约束,使得两张表形成了三种了关系: 多对一 多对多 一对一 二.重点理解如果找出两张表之间的关系 分析步骤: #1.先站在左表的角度去找 是否左表的多条记录可以 ...

  10. Spark 计算人员三度关系

    1.一度人脉:双方直接是好友 2.二度人脉:双方有一个以上共同的好友,这时朋友网可以计算出你们有几个共同的好友并且呈现数字给你.你们的关系是: 你->朋友->陌生人 3.三度人脉:即你朋友 ...

随机推荐

  1. Win10 UEFI 系统安装教程

    1:首先我们需要先拿一个U盘,制作一个带UEFI PE.(网上的大白菜以及老毛桃都可以,我用的是从网上找的WIN10 PE.WIN10 PE的好处是集成了NVME驱动,可以认得到SM951 NVME版 ...

  2. Linux设置SSH隧道连接

    因为安全考虑,服务器防火墙对某些端口进行了限制,原先通过客户端工具可以连接的端口,现在不能连接了,需要通过设置SSH隧道才可以,记录如下.

  3. Mysql系列(一)—— 基于5.7.22 解压版下载、安装、配置和卸载

    1.下载 从官网中直接获取自己想要的版本: MySQL Community Server 5.7.22 2.解压 将下载到的文件解压缩到自己喜欢的位置. 与mysql 5.6不同的是5.7版本中没有d ...

  4. c#栈的用法

    栈是一种重要的线性结构,栈和队列是限定插入和删除只能在表的“端点”进行的线性表 –栈的元素必须“后进先出”. –栈的操作只能在这个线性表的表尾进行. –注:对于栈来说,这个表尾称为栈的栈顶(top), ...

  5. [K8s 1.9实践]Kubeadm 1.9 HA 高可用 集群 本地离线镜像部署

    k8s介绍 k8s 发展速度很快,目前很多大的公司容器集群都基于该项目,如京东,腾讯,滴滴,瓜子二手车,北森等等. kubernetes1.9版本发布2017年12月15日,每是那三个月一个迭代, W ...

  6. C# 取得对象属性类型

    1.对象 Object obj; 2.对象属性 Type postType = obj.GetType(); PropertyInfo[] postTypeInfos = postType.GetPr ...

  7. Ablation Study

    We often come across 'ablation study' in machine learning papers, for example, in this paper with th ...

  8. 任意图像尺寸变成目标尺寸(包含相应的boxes的变换)

    def image_preporcess(image, target_size, gt_boxes=None): image = cv2.cvtColor(image, cv2.COLOR_BGR2R ...

  9. XSS挑战之旅---游戏通关攻略

    最近发现一个有趣的XSS闯关小游戏,游戏的作者是先知社区的大佬Mramydnei,喜欢XSS的大家可以一起来学习交流. 现在我把自己在前面的十八关里面的闯关过程记录一下,大神绕行,我是菜鸟,大家可以一 ...

  10. Float型 与 Double型数据的存储方式

    先来了解一下浮点数在计算机中是以什么形式存储的 首先要知道计算机能懂得只有0和1,每一个0和1都占一个位 bit (比特)(Binary Digits):存放一位二进制数,最小的存储单位. 而对于存放 ...