接上文,我们已经创建了基本的关系以及表实体,以下是通过图方式的查询

参考关系图

代码处理

  • 创建图数据
func CreateGraph(ctx context.Context, client *ent.Client) error {
 // first, create the users.
 a8m, err := client.User.
  Create().
  SetAge(30).
  SetName("Ariel").
  Save(ctx)
 if err != nil {
  return err
 }
 neta, err := client.User.
  Create().
  SetAge(28).
  SetName("Neta").
  Save(ctx)
 if err != nil {
  return err
 }
 // then, create the cars, and attach them to the users in the creation.
 _, err = client.Car.
  Create().
  SetModel("Tesla").
  SetRegisteredAt(time.Now()). // ignore the time in the graph.
  SetOwner(a8m). // attach this graph to Ariel.
  Save(ctx)
 if err != nil {
  return err
 }
 _, err = client.Car.
  Create().
  SetModel("Mazda").
  SetRegisteredAt(time.Now()). // ignore the time in the graph.
  SetOwner(a8m). // attach this graph to Ariel.
  Save(ctx)
 if err != nil {
  return err
 }
 _, err = client.Car.
  Create().
  SetModel("Ford").
  SetRegisteredAt(time.Now()). // ignore the time in the graph.
  SetOwner(neta). // attach this graph to Neta.
  Save(ctx)
 if err != nil {
  return err
 }
 // create the groups, and add their users in the creation.
 _, err = client.Group.
  Create().
  SetName("GitLab").
  AddUsers(neta, a8m).
  Save(ctx)
 if err != nil {
  return err
 }
 _, err = client.Group.
  Create().
  SetName("GitHub").
  AddUsers(a8m).
  Save(ctx)
 if err != nil {
  return err
 }
 log.Println("The graph was created successfully")
 return nil
}
 
  • 查询组名称为github 的用户以及汽车
func QueryGithub(ctx context.Context, client *ent.Client) error {
 cars, err := client.Group.
  Query().
  Where(group.Name("GitHub")). // (Group(Name=GitHub),)
  QueryUsers(). // (User(Name=Ariel, Age=30),)
  QueryCars(). // (Car(Model=Tesla, RegisteredAt=<Time>), Car(Model=Mazda, RegisteredAt=<Time>),)
  All(ctx)
 if err != nil {
  return fmt.Errorf("failed getting cars: %v", err)
 }
 log.Println("cars returned:", cars)
 // Output: (Car(Model=Tesla, RegisteredAt=<Time>), Car(Model=Mazda, RegisteredAt=<Time>),)
 return nil
}
  • 查询用户Ariel 的车
func QueryArielCars(ctx context.Context, client *ent.Client) error {
 // Get "Ariel" from previous steps.
 a8m := client.User.
  Query().
  Where(
   user.HasCars(),
   user.Name("Ariel"),
  ).
  OnlyX(ctx)
 cars, err := a8m. // Get the groups, that a8m is connected to:
    QueryGroups(). // (Group(Name=GitHub), Group(Name=GitLab),)
    QueryUsers(). // (User(Name=Ariel, Age=30), User(Name=Neta, Age=28),)
    QueryCars(). //
    Where( //
   car.Not( // Get Neta and Ariel cars, but filter out
    car.ModelEQ("Mazda"), // those who named "Mazda"
   ), //
  ). //
  All(ctx)
 if err != nil {
  return fmt.Errorf("failed getting cars: %v", err)
 }
 log.Println("cars returned:", cars)
 // Output: (Car(Model=Tesla, RegisteredAt=<Time>), Car(Model=Ford, RegisteredAt=<Time>),)
 return nil
}
  • 查询包含用户的组
func QueryGroupWithUsers(ctx context.Context, client *ent.Client) error {
 groups, err := client.Group.
  Query().
  Where(group.HasUsers()).
  All(ctx)
 if err != nil {
  return fmt.Errorf("failed getting groups: %v", err)
 }
 log.Println("groups returned:", groups)
 // Output: (Group(Name=GitHub), Group(Name=GitLab),)
 return nil
}
​

查询sql

为了查看生成的sql,我启用了慢查询处理

set global long_query_time=0;
set global slow_query_log=1;
  • 生成的sql
    以下是一个查询的sql,我进行了格式化
 
SELECT
    DISTINCT `cars`.`id`,
    `cars`.`model`,
    `cars`.`registered_at`
FROM
    `cars`
    JOIN (
        SELECT
            `users`.`id`
        FROM
            `users`
            JOIN (
                SELECT
                    `group_users`.`user_id`
                FROM
                    `group_users`
                    JOIN (
                        SELECT
                            `groups`.`id`
                        FROM
                            `groups`
                            JOIN (
                                SELECT
                                    `group_users`.`group_id`
                                FROM
                                    `group_users`
                                    JOIN `users` AS `t0` ON `group_users`.`user_id` = `t0`.`id`
                                WHERE
                                    `t0`.`id` = 10
                            ) AS `t1` ON `groups`.`id` = `t1`.`group_id`
                    ) AS `t1` ON `group_users`.`group_id` = `t1`.`id`
            ) AS `t1` ON `users`.`id` = `t1`.`user_id`
    ) AS `t1` ON `cars`.`owner_id` = `t1`.`id`
WHERE
    NOT (`cars`.`model` = 'Mazda');
 
 

查看查询计划

EXPLAIN SELECT DISTINCT `cars`.`id`, `cars`.`model`, `cars`.`registered_at` FROM `cars` JOIN (SELECT `users`.`id` FROM `users` JOIN (SELECT `group_users`.`user_id` FROM `group_users` JOIN (SELECT `groups`.`id` FROM `groups` JOIN (SELECT `group_users`.`group_id` FROM `group_users` JOIN `users` AS `t0` ON `group_users`.`user_id` = `t0`.`id` WHERE `t0`.`id` = 10) AS `t1` ON `groups`.`id` = `t1`.`group_id`) AS `t1` ON `group_users`.`group_id` = `t1`.`id`) AS `t1` ON `users`.`id` = `t1`.`user_id`) AS `t1` ON `cars`.`owner_id` = `t1`.`id` WHERE NOT (`cars`.`model` = 'Mazda');
 

说明:
从上边可以看出通过索引进行了优化,还是比较高效的

参考资料

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

ent 基本使用四 图遍历查询的更多相关文章

  1. OO第四单元总结——查询UML类图 暨 OO课程总结

    一.本单元两次作业的架构设计总结 作业一.UML类图查询 1. 统计信息图 2. 复杂度分析 基本复杂度(Essential Complexity (ev(G)).模块设计复杂度(Module Des ...

  2. CASE函数 sql server——分组查询(方法和思想) ref和out 一般处理程序结合反射技术统一执行客户端请求 遍历查询结果集,update数据 HBuilder设置APP状态栏

    CASE函数   作用: 可以将查询结果集的某一列的字段值进行替换 它可以生成一个新列 相当于switch...case和 if..else 使用语法: case 表达式/字段 when 值 then ...

  3. 20162327WJH实验四——图的实现与应用

    20162327WJH实验四--图的实现与应用 实 验 报 告 课程:程序设计与数据结构 班级: 1623 姓名: 王旌含 学号:20162327 成绩: 指导教师:娄嘉鹏 王志强 实验日期:11月2 ...

  4. Gremlin:图遍历语言

    Gremlin简介 Gremlin是Apache TinkerPop 框架下的图遍历语言.Gremlin是一种函数式数据流语言,可以使得用户使用简洁的方式表述复杂的属性图(property graph ...

  5. 《数据结构与算法(C语言版)》严蔚敏 | 第五章 建立二叉树,并完成三/四种遍历算法

    PS:所有的代码示例使用的都是这个图 2019-10-29 利用p126的算法5.3建立二叉树,并完成三种遍历算法 中序 后序 先序 #include<iostream> #include ...

  6. java map的四种遍历

    四种遍历: public static void main(String[] args) { Map<String, String> map = new HashMap<String ...

  7. lua中for循环的四种遍历方式

    lua中for的四种遍历方式区别 table.maxn 取最大的整数key #table 从1开始的顺序整数最大值,如1,2,3,6 #table == 3   key,value pairs 取每一 ...

  8. MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析

    文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...

  9. Map的四种遍历

    //Map的四种遍历方法 public static void main(String[] args) { Map<String, String> map = new HashMap< ...

随机推荐

  1. Linux命令注释—HDFS运维

    HDFS运维—命令注释 1 实验背景 HDFS是大数据其他组件的基础,Hive的数据存储在HDFS中,Mapreduce.Spark 等计算数据也存储在HDFS 中,HBase 的 region 也是 ...

  2. 移动开发首页业界资讯移动应用平台技术专题 输入您要搜索的内容 基于Java Socket的自定义协议,实现Android与服务器的长连接(二)

    在阅读本文前需要对socket以及自定义协议有一个基本的了解,可以先查看上一篇文章<基于Java Socket的自定义协议,实现Android与服务器的长连接(一)>学习相关的基础知识点. ...

  3. ClassPathBeanDefinitionScanner 说明

    Spring 工具类 ClassPathBeanDefinitionScanner 组件Bean定义扫描https://blog.csdn.net/andy_zhang2007/article/det ...

  4. SQL Server外键关系是强制约束,外键值也可以是空(NULL)

    在SQL Server中,实际上外键值可不可以为空(NULL),和外键关系是不是强制约束无关. 我们先在SQL Server数据库中建立两张表People和Car,一个People可以有多个Car,所 ...

  5. scratch学习研究心得_逐步更新

    2019-10-30: Scratch对对象a克隆,不能选择克隆自己,这样可能下次一下子同时产生两个克隆体,要设置克隆a scratch3.0采用全新html5技术,图片和其他对象放大缩小,效果几乎不 ...

  6. C# 索引器(C#学习笔记05)

    索引器 索引器能够使对象像数组一样被索引,使用数组的访问方式 object[x] 索引器的声明在某种程度上类似于属性的声明,例如,使用 get 和 set 方法来定义一个索引器. 不同的是,属性值的定 ...

  7. HTML转换特效相关插件

    Arctext.js Arctext.js 是基于 Lettering.js 的文字旋转插件,根据设置的旋转半径准确计算每个字母的旋转弧度并均匀分布. 虽然 CSS3 也能够实现字符旋转效果,但是要让 ...

  8. DOM创建节点

    1.DOM--document object model 常用的节点类型: 元素节点:(标签) 属性节点:(标签里的属性) 文本节点:(文本节点) 2,document有个属性叫nodetype,返回 ...

  9. 【转】Webpack 快速上手(中)

    由于文章篇幅较长,为了更好的阅读体验,本文分为上.中.下三篇: 上篇介绍了什么是 webpack,为什么需要 webpack,webpack 的文件输入和输出 中篇介绍了 webpack 在输入和输出 ...

  10. 好用的随查工具Dash

    1. 好用的随查工具Dash 1.1. mac版本推荐 推荐一个很好用的工具,名字就叫Dash,当然缺点就是只有英文版,中文版可能也有但更新肯定不如英文及时 可以自由下载各种文档,比如下面的这图,左侧 ...