V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
adjusted
V2EX  ›  分享创造

Queryx: 开源一个支持数据库自动管理的 Go ORM

  •  4
     
  •   adjusted ·
    wangzuo · 2023-07-05 12:22:46 +08:00 · 7206 次点击
    这是一个创建于 512 天前的主题,其中的信息可能已经有所发展或是发生改变。

    话不多说直接上地址: https://github.com/swiftcarrot/queryx

    一键安装:

    curl -sf https://raw.githubusercontent.com/swiftcarrot/queryx/main/install.sh  | sh
    

    schema.hcl

    Queryx 使用 schema.hcl 来描述数据库,在以下例子中定义了数据库环境以及数据库模型。

    database "db" {
      adapter = "postgresql"
    
      config "development" {
        url = "postgres://postgres:postgres@localhost:5432/blog_development?sslmode=disable"
      }
    
      config "production" {
        url = env("DATABASE_URL")
      }
    
      generator "client-golang" {}
    
      model "Post" {
        column "title" {
          type = string
        }
        column "content" {
          type = text
        }
      }
    }
    

    运行 queryx db:create 命令创建 postgres 数据库,然后运行 queryx db:migrate,就可以自动创建对应的 migration 文件和数据库结构。

    CRUD

    运行 queryx gdb 目录下会生成对应的 ORM 代码, 生成的代码根据数据库生成对应的 Go 类型。生成的代码除了 driver 之外没有其他第三方依赖,我们也希望自动生成的代码简洁可读。

    下面是一些 CRUD 操作的示例代码:

    // 创建
    newPost := c.ChangePost().SetTitle("post title")
    post, err := c.QueryPost().Create(newPost)
    
    // 查询
    post, err := c.QueryPost().Find(1)
    posts, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).All()
    
    // 更新
    updatePost := c.ChangePost().SetTitle("new post title")
    err := post.Update(updatePost)
    updated, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).UpdateAll(updatePost)
    
    // 删除
    err := post.Delete()
    deleted, err := c.QueryPost().Where(c.PostTitle.EQ("post title")).DeleteAll()
    

    关系

    schema.hcl 也可以声明各个 model 之间的关系,包括 belongs_to, has_one, has_many,例如:

    model "User" {
      belongs_to "group" {}
    
      column "name" {
        type = string
      }
    }
    
    model "Group" {
      has_many "users" {}
    
      column "name" {
        type = string
      }
    }
    

    声明关系之后,你可以使用生成的 preload方法来避免 n+1 查询,比如:

    users, err := c.QueryUser().PreloadGroup().All()
    // users[0].Groups
    
    groups, err := c.QueryGroup().PreloadUsers().All()
    // groups[0].User
    

    如果你熟悉 Rails ,就会发现 Queryx 参考了很多 ActiveRecord 的设计,我们希望能够复制 ActiveRecord 的开发体验。更多操作请参阅 README 文档,并欢迎在 issue, discussion 以及回复中交流。Queryx 目前仍处于测试阶段,许多功能仍在开发中,比如 TypeScript 的版本。我们希望在后续版本中继续提升开发体验。

    第 1 条附言  ·  2023-07-10 11:45:29 +08:00

    v0.1.7 添加了 mysql 和 sqlite 支持,只需要修改对应的 adapter:

    database "db" {
      adapter = "mysql"
    
      config "development" {
        url = "root@tcp(localhost:3306)/queryx_test?parseTime=true"
      }
    }
    
    database "db" {
      adapter = "sqlite"
    
      config "test" {
        url = "file:test.sqlite3"
      }
    }
    
    第 2 条附言  ·  2023-07-27 22:30:06 +08:00
    32 条回复    2023-08-22 21:45:32 +08:00
    Mo3et
        1
    Mo3et  
       2023-07-05 12:28:00 +08:00   ❤️ 1
    不错不错 帮顶! 周末研究下
    hooopo
        2
    hooopo  
       2023-07-05 13:11:21 +08:00   ❤️ 1
    cool
    dw2693734d
        3
    dw2693734d  
       2023-07-05 15:53:14 +08:00 via iPhone
    牛逼, repliacation 可以设置吗
    adjusted
        4
    adjusted  
    OP
       2023-07-05 16:04:37 +08:00   ❤️ 1
    @dw2693734d 暂时还不支持 replica / cluster ,应该可以通过自定义 adapter 来实现,我们目前主要工作还是在确认 ORM API 的设计。
    dw2693734d
        5
    dw2693734d  
       2023-07-05 16:18:48 +08:00 via iPhone   ❤️ 1
    @adjusted rails dev 支持一波,这种 migration 很喜欢
    FightPig
        6
    FightPig  
       2023-07-05 23:38:23 +08:00   ❤️ 1
    用 rails 的人大喜
    timnottom
        7
    timnottom  
       2023-07-06 09:40:45 +08:00
    命令行工具名称简洁点啊,比如:qx

    弄个 queryx 看着别扭
    adjusted
        8
    adjusted  
    OP
       2023-07-06 09:55:42 +08:00
    @timnottom 有道理,可以考虑!
    waltcow
        9
    waltcow  
       2023-07-06 11:29:53 +08:00
    和 ent 有啥区别
    Mistyrainjn
        10
    Mistyrainjn  
       2023-07-06 11:40:10 +08:00
    为啥没有中文文档
    adjusted
        11
    adjusted  
    OP
       2023-07-06 11:59:15 +08:00
    @Mistyrainjn 还在编辑
    adjusted
        12
    adjusted  
    OP
       2023-07-06 12:00:50 +08:00
    @waltcow queryx 没有采用图模型来处理关系,生成的代码相对比较简单(除了 driver 之外没有第三方依赖),最大的区别是 queryx 还会支持其他语言,比如 typescript
    zoharSoul
        13
    zoharSoul  
       2023-07-06 16:29:15 +08:00
    其实我一直没搞懂, 根据 model 生成数据库这种需求是什么时候会用到...
    建表/修改表结构, 不是都要走 sql 上线审批的吗?
    adjusted
        14
    adjusted  
    OP
       2023-07-06 17:39:21 +08:00
    @zoharSoul 说一下个人的理解
    1. 声明式开发体验更好
    2. sql 自动化过程可以加入一些自动检查,生成最佳实践的 sql
    3. 生成的 migration sql 上线前还是可以走人工检查,不矛盾
    zoharSoul
        15
    zoharSoul  
       2023-07-06 18:35:32 +08:00
    @adjusted #14
    我说的不是 1,2 这种查询的
    单纯指自动建表, 自动建库
    hxtheone
        16
    hxtheone  
       2023-07-06 18:45:23 +08:00 via iPhone
    帮顶,但说实话作为前 rails dev ,从没用过 activerecord 的 migration ,都是直接怼 sql …
    adjusted
        17
    adjusted  
    OP
       2023-07-06 19:26:36 +08:00
    @zoharSoul 是指建表和修改表格的 sql
    adjusted
        18
    adjusted  
    OP
       2023-07-06 19:27:36 +08:00
    @hxtheone 我也不喜欢写 migration ,所以默认自动生成 migration sql ,减少心智负担
    dw2693734d
        19
    dw2693734d  
       2023-07-07 13:52:16 +08:00
    @hxtheone 那多人协作是不是挺麻烦的
    adjusted
        20
    adjusted  
    OP
       2023-07-07 21:43:56 +08:00
    @dw2693734d 都提交到 git 里面,问题应该不大
    THESDZ
        21
    THESDZ  
       2023-07-12 08:45:56 +08:00
    @zoharSoul #13
    1.微服务导致数据库变多,sql 也就变多.
    2.ci/cd 自动化(最起码开发环境下),数据库也是发版内容,也期望自动化.
    3.团队合作,人员参差不齐,人员变动等,可能导致数据库版本的管理与服务版本混乱.

    所以:
    1.数据库版本控制自动化和标准化势在必行(起码是个趋势)

    ps: 个人认为 model 只是一种对于数据库版本的表达而已.👀
    adjusted
        22
    adjusted  
    OP
       2023-07-12 10:38:18 +08:00
    @THESDZ schema 作为"单一真相来源",之后也可以用来生成文档和图表
    THESDZ
        23
    THESDZ  
       2023-07-13 08:58:20 +08:00
    @adjusted #22 schema 并非单一真相,大多数的程序对接的存储介质并非一个,而程序却可以唯一(微服务场景下,每个服务原子化了),我倾向于,schema 做为底层,由程序自动化控制,在上线之后的生命周期中,不应该接触到 schema,而只能接触到程序,所以文档,图表均应该通过程序生成,而非 schema(schema 可以做为一个数据的来源,但不能做为直接源和单一源)
    adjusted
        24
    adjusted  
    OP
       2023-07-14 09:54:24 +08:00
    @THESDZ schema 也可以支持多个数据源
    songray
        25
    songray  
       2023-07-14 13:08:47 +08:00
    想必是参加 ruby conf 2023 的那个老哥?
    wangritian
        26
    wangritian  
       2023-07-28 00:24:42 +08:00
    我是通过 go struct 上写注解生成创建/修改表结构的 sql 语句的,服务启动时由选举出的 leader 执行,用了几年了,很爽
    添加表、添加字段、修改字段默认执行,删除字段、删除表仅打印提示,我再手动执行
    adjusted
        27
    adjusted  
    OP
       2023-07-28 10:12:48 +08:00
    @wangritian 是的,手写 migration sql 心智负担太大了
    gemini
        28
    gemini  
       2023-08-05 12:33:23 +08:00
    看上去有点像 prisma… 先收藏
    adjusted
        29
    adjusted  
    OP
       2023-08-05 19:23:11 +08:00
    @gemini queryx 用的原生 driver ,生成的代码比较简单,我们都是直接 checkin 到 git
    vmlinz
        30
    vmlinz  
       2023-08-22 20:10:04 +08:00 via iPhone
    最近刚好看 golang orm

    目前看了 gorm ,sqlc

    migration 管理的话用 go-migrate ,还有一个 altlas ,也是用 hcl 定义 schema 。
    vmlinz
        31
    vmlinz  
       2023-08-22 20:21:44 +08:00 via iPhone
    adjusted
        32
    adjusted  
    OP
       2023-08-22 21:45:32 +08:00   ❤️ 1
    @vmlinz queryx 的自动 migration 是基于 atlas (readme 中有提到),我们也和 atlas 团队一直有沟通。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5789 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 06:07 · PVG 14:07 · LAX 22:07 · JFK 01:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.