如何在GraphQL中为Customer Schema关联已存在的自定义Orders类型?
问题:在代码优先的GraphQL Schema中关联已存在的类型
问题背景
项目采用代码优先方式构建GraphQL Schema:
- 每个实体用独立JSON模型定义参数,示例:
// Customer 模型 { "customerId": { "type": "String" }, "customerName": { "type": "String" }, "customerProperties": { "type": "object" // ... 其他属性 } } // Orders 模型 { "customerId": { "type": "string" }, // ... 其他详情 }
- 编译阶段通过自定义工具将JSON模型转换为
graphql库中的GraphQLObjectType实例,每个实体对应一个独立的类型实例。
现在需要给Customer类型添加与Orders的关联,期望生成的Schema效果:
type Customer { id: String, name: String, orders: Orders }
但尝试在Customer的类型工厂中直接创建新的Orders类型实例时,报错:"Schema must contains unique named types but contains multiple names "Orders"",需要找到通过类型名称关联已存在Orders类型的方法。
解决方案
核心思路是复用已创建的Orders类型实例,而不是重新创建,具体实现方式如下:
1. 维护全局类型注册表
在类型生成的自定义工具中,创建一个全局的类型映射表(比如typeRegistry),每当生成一个GraphQLObjectType实例时,就将其以类型名称为key存入注册表:
// 全局类型注册表 const typeRegistry = {}; // 生成Orders类型的逻辑 const OrdersType = new GraphQLObjectType({ name: 'Orders', fields: () => ({ // ... Orders的字段定义 }) }); // 存入注册表 typeRegistry['Orders'] = OrdersType;
2. 在Customer类型中引用注册表中的实例
在定义Customer类型的关联字段时,直接从注册表中取出已存在的Orders类型实例,而不是重新创建:
const CustomerType = new GraphQLObjectType({ name: 'Customer', fields: () => ({ id: { type: GraphQLString }, name: { type: GraphQLString }, // 从注册表获取已存在的Orders类型 orders: { type: typeRegistry['Orders'], // 可选:添加resolve函数处理关联数据查询 resolve: (parent) => { // 根据parent.customerId查询对应的Orders数据 } } }) });
3. 处理循环依赖(如果存在)
如果Customer和Orders存在双向关联(比如Orders也需要关联Customer),可以使用函数式字段定义(即fields设为返回对象的函数),确保在访问字段时类型已经被初始化并存入注册表:
// Orders类型中关联Customer const OrdersType = new GraphQLObjectType({ name: 'Orders', fields: () => ({ customerId: { type: GraphQLString }, customer: { type: typeRegistry['Customer'], resolve: (parent) => { // 根据parent.customerId查询对应的Customer数据 } } }) });
这样就能避免重复创建同名类型,同时实现实体间的关联。
内容的提问来源于stack exchange,提问作者Nikita Polevoy
相关产品推荐
相关产品推荐

