[译文] Go:ent,基于图的 ORM 框架 - Facebook 出品 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
darluc
V2EX    Go 编程语言

[译文] Go:ent,基于图的 ORM 框架 - Facebook 出品

  •  
  •   darluc 2020 年 6 月 22 日 9515 次点击
    这是一个创建于 2115 天前的主题,其中的信息可能已经有所发展或是发生改变。

    阅读全文

    :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 框架一样对多个领域的多个节点进行聚合,所以性能总会不错。对查询做一个快速的跑分,可以看出代码包增加了多少额外的工作:

    阅读全文

    7 条回复    2022-04-29 00:13:30 +08:00
    darksword21
        1
    darksword21  
    PRO
       2020 年 6 月 22 日 via iPhone
    最近在用,只是不知道 json 要 decode 到嵌套的 struct 的时候 scheme 改怎么写,很困惑
    AlphaTr
        2
    AlphaTr  
       2020 年 6 月 22 日
    补一个 github 的地址 https://github.com/facebookincubator/ent
    notamail
        3
    notamail  
       2020 年 6 月 22 日
    @darksword21 field.JSON("xxxx", SomeStruct{}) 这样就可以了
    darksword21
        4
    darksword21  
    PRO
       2020 年 6 月 22 日 via iPhone
    @notamail 我也试过,但是这个 struct 如何直接写在里面例如 field.JSON(”xxx”, Mystruct{Key1, Key2 string})这样可以吗
    notamail
        5
    notamail  
       2020 年 6 月 23 日 via Android   1
    @darksword21 第二个参数是实例化的,不是类型,struct{Key1,Key2 string}{}即可
    kssss
        6
    kssss  
       2020 年 11 月 25 日
    这个不支持条件更新啊,就比如说把 用户表里面年龄大于 30 的 所有用户的余额增加 100,类似 SQL 的 update column = column + 100,这条语句怎么写?
    dcoder
        7
    dcoder  
       2022 年 4 月 29 日
    整的真复杂...
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1100 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 17:26 PVG 01:26 LAX 10:26 JFK 13:26
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86