# 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 可以有多条 service(1:N) ## 3. 代码生成 在项目根目录执行: ```bash go run entgo.io/ent/cmd/ent generate ./app/game/rpc/internal/models/schema ``` 如果你后续为 schema 增加了注解或字段,重复执行同一命令即可刷新生成代码。 ## 4. 业务查询示例 > 以下为典型写法,具体包路径以你项目实际生成结果为准。 ### 4.1 查询某个玩家及其所有服务 ```go player, err := client.Players. Query(). Where(players.ID(playerID)). WithServices(). Only(ctx) ``` ### 4.2 查询某个店铺及其成员关系记录 ```go shop, err := client.Shops. Query(). Where(shops.ID(shopID)). WithMemberships(). Only(ctx) ``` ### 4.3 查询某玩家收到的邀请 ```go invitations, err := client.Players. QueryReceivedInvitations(player). All(ctx) ``` ## 5. 常见坑 - `edge.From(...).Field(...)` 的字段名必须是当前 schema 里真实存在的字段。 - `Ref("...")` 名称要和对端 `edge.To("...")` 保持一致。 - 同一实体指向同一目标实体的多条边(例如邀请的 `player` 和 `inviter`)必须使用不同 edge 名称,避免代码生成冲突。 - 如果 SQL 没有声明外键但你定义了带 `Field(...)` 的 edge,迁移时可能会生成外键约束;若不想生成,请保持和 SQL 一致或在迁移层显式控制。 ## 6. 当前文件位置 - Schema 目录:`app/game/rpc/internal/models/schema` - SQL 来源:`desc/sql/game`