Golang Go语言中的ent,基于图的ORM框架 - Facebook 出品

发布于 1周前 作者 vueper 来自 Go语言

Golang Go语言中的ent,基于图的ORM框架 - Facebook 出品

阅读全文

:information_source: 本文基于处于开发中的项目的主分支

ent 是由 Facebook Connectivity 团队创建的 ORM 框架。迫于 Go 社区中缺少能够像图一样查询数据的工具,同时也缺少 100% 类型安全的 ORM,ent 就是被设计出来解决这些问题的

图的概念

ent 用一组实体和边线来表达图的概念,并且没有任何限制。我们使用代码库中现成的例子进行说明:

此例子中,有三个实体对象,GroupUserPet ,它们相互关联在一起,可以用多种方式遍历。这个图可以利用项目中的 entc 工具来描述,使用命令 entc describe

实体之间的关系由边线表示,它们在内部被转换为字段,表和外键。这里是在 MySQL 中转换成的数据库图表:

传统的 ORM 框架把每个关系显示地申明在实体上,与此不同,ent 只暴露了实体的属性和一个用于遍历这些实体边线的方法。

查询

这个项目提供了优秀的文档和各种不同 ORM 查询和使用的例子。让我们来看一个涉及所有实体的查询例子:

管理员用户的朋友中,我们想要获得他们的宠物的朋友的主人

以下是这个查询的示意图:

例子中建议的查询是可自我描述的:

如上一段所示,每个实体都暴露了方法用来顺着它们的边线进行查询:Group 通过 QueryAdmin() 方法暴露了 admin 边线,它自己又通过 QueryFriends() 暴露了它的 friends 边线,等等。代码生成是用来创建这些方法的核心工具。

代码生成

通过 entc 命令可以进行代码生成,它是项目的核心部件而且它使这个项目更加强大。模板引擎是代码生成的基础,它允许开发者修改查询语句,并依照他们的需求暴露各种方法,使得 ORM 足够灵活能够任意地定制。

默认的实体模板会提供所有的文件和方法用于创建、更新、删除和遍历查询每个实体对象以及它们的关系边。无论如何,在代码生成中一切都是模板。你可以制定它与数据库的交流方式,数据迁移等等。

这个项目还提供了一个实现了 GraphQL Node 接口的模板示例。生成的代码使得我们的实体对象都能兼容这个接口:

模板系统能生成完美契合你的项目的代码。

性能

现在来到有趣的部分了,看看底层的查询是如何构建的。这里以 MySQL 为例,上例中生成的查询如下:

这个 ORM 使用嵌套查询来实现无限制地遍历查询。不过使用 join 查询也是可行的。这是与嵌套查询等效的使用 join 的查询:

虽然嵌套的查询更容易读,由于是一层层的 select 语句嵌套出来的,大多数情况下,join 语句执行更快。不过,在这个案例中,由于 ORM 遍历数据使用的边线是相关的索引,服务器生成的查询计划是一样的:

plan for the subqueries

<center><small>plan for the subqueries</small></center>

plan for the join

<center><small>plan for the join</small></center>

这个 ORM 框架还支持更复杂的查询通过图来查询节点,比如:

我们想要获得所有的宠物,它们的朋友的主人是 admin 成员组的朋友

这个查询的 SQL 写起来非常难。使用常规的 ORM 框架几乎是个不可能完成的任务,不过用 ent 写起来却非常简单:

而且, ent 不需要像传统 ORM 框架一样对多个领域的多个节点进行聚合,所以性能总会不错。对查询做一个快速的跑分,可以看出代码包增加了多少额外的工作:

阅读全文


更多关于Golang Go语言中的ent,基于图的ORM框架 - Facebook 出品的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

最近在用,只是不知道 json 要 decode 到嵌套的 struct 的时候 scheme 改怎么写,很困惑

更多关于Golang Go语言中的ent,基于图的ORM框架 - Facebook 出品的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


field.JSON(“xxxx”, SomeStruct{}) 这样就可以了

我也试过,但是这个 struct 如何直接写在里面例如 field.JSON(”xxx”, Mystruct{Key1, Key2 string})这样可以吗

第二个参数是实例化的,不是类型,struct{Key1,Key2 string}{}即可

这个不支持条件更新啊,就比如说把 用户表里面年龄大于 30 的 所有用户的余额增加 100,类似 SQL 的 update column = column + 100,这条语句怎么写?

整的真复杂…

ent是Facebook出品的基于图的Golang ORM(对象关系映射)框架,它提供了强大的功能和灵活性,特别适用于处理复杂的数据库结构和关系。以下是对ent框架的简要评价:

优势

  1. schema即代码:ent允许开发者使用Go的结构体来定义数据库表模型,通过代码生成工具可以自动生成数据库表和相关操作代码,大大简化了数据库开发流程。
  2. 图遍历能力:ent支持基于图的遍历,使得处理具有复杂关联的数据变得更为直观和方便。
  3. 静态类型:ent生成的代码是静态类型的,这有助于在编译期间发现潜在的类型错误,提高代码的健壮性。
  4. 多种存储引擎支持:ent支持多种数据库存储引擎,如MySQL、SQLite等,提供了良好的数据库兼容性。

注意事项

  1. 学习成本:ent的schema设计和DSL(领域特定语言)需要一定的学习成本,初学者可能会觉得上手较难。
  2. 代码生成量:对于大型项目,ent生成的代码量可能会较大,需要合理管理以避免代码冗余。

总的来说,ent是一个功能强大且灵活的Golang ORM框架,特别适合处理复杂的数据库结构和关系。然而,它也需要一定的学习成本来掌握其schema设计和DSL。如果你正在寻找一个能够处理复杂数据库关系的Golang ORM框架,ent无疑是一个值得考虑的选择。

回到顶部