Files
2026-02-28 05:33:16 +08:00

2.8 KiB
Raw Permalink Blame History

Ent Edges 使用说明(game 模块)

本文说明 app/game/rpc/internal/models/schema 下 Edges 的定义方式、生成方式,以及在业务代码中如何使用。

1. 当前 game 模块关系设计

基于 desc/sql/game 的表结构,当前主要关系:

  • players 1:N player_services
    • player_services.player_id -> players.id
  • shops 1:N shop_players
    • shop_players.shop_id -> shops.id
  • players 1:N shop_players(逻辑关联)
    • shop_players.player_id -> players.id
  • shops 1:N shop_invitations
    • shop_invitations.shop_id -> shops.id
  • players 1:N shop_invitations(收到邀请)
    • shop_invitations.player_id -> players.id
  • players 1:N shop_invitations(发起邀请)
    • shop_invitations.invited_by -> players.id

2. Edge 定义规则

2.1 在子表(持有外键字段)上定义 edge.From(...).Field(...)

示例(player_services):

  • edge.From("player", Players.Type).Ref("services").Field("player_id").Required().Unique()

含义:

  • 当前实体(player_services)通过 player_id 指向一个 players
  • Unique() 表示每条 player_services 记录只对应一个 player(典型 N:1 子侧定义)

2.2 在父表定义反向 edge.To(...)

示例(players):

  • edge.To("services", PlayerServices.Type)

含义:

  • 一个 player 可以有多条 service1:N

3. 代码生成

在项目根目录执行:

go run entgo.io/ent/cmd/ent generate ./app/game/rpc/internal/models/schema

如果你后续为 schema 增加了注解或字段,重复执行同一命令即可刷新生成代码。

4. 业务查询示例

以下为典型写法,具体包路径以你项目实际生成结果为准。

4.1 查询某个玩家及其所有服务

player, err := client.Players.
    Query().
    Where(players.ID(playerID)).
    WithServices().
    Only(ctx)

4.2 查询某个店铺及其成员关系记录

shop, err := client.Shops.
    Query().
    Where(shops.ID(shopID)).
    WithMemberships().
    Only(ctx)

4.3 查询某玩家收到的邀请

invitations, err := client.Players.
    QueryReceivedInvitations(player).
    All(ctx)

5. 常见坑

  • edge.From(...).Field(...) 的字段名必须是当前 schema 里真实存在的字段。
  • Ref("...") 名称要和对端 edge.To("...") 保持一致。
  • 同一实体指向同一目标实体的多条边(例如邀请的 playerinviter)必须使用不同 edge 名称,避免代码生成冲突。
  • 如果 SQL 没有声明外键但你定义了带 Field(...) 的 edge,迁移时可能会生成外键约束;若不想生成,请保持和 SQL 一致或在迁移层显式控制。

6. 当前文件位置

  • Schema 目录:app/game/rpc/internal/models/schema
  • SQL 来源:desc/sql/game