Apollo GraphQL Schema Stitching跨模块类型解析问题求助
解决Schema Stitching中跨模块类型属性的解析问题
我之前也碰到过类似的困扰,Schema Stitching实现可组合性的时候,最容易卡壳的就是跨模块类型的属性解析——特别是像你这种Referer依赖Referee的场景。先把你提到的完整场景理清楚:
原始单Schema结构
type Referee { id: ID! stringProp: String! } type Referer { id: ID! pointer: Referee! } type Query { referers: [Referer] }
对应的解析器能把仅含id的对象扩展成完整字段,支持这样的查询:
query FromSingleSchema { referers { id pointer { id stringProp } } }
现在拆分到不同模块后,你应该是遇到了Referer模块里的pointer字段无法正确解析Referee的stringProp属性的问题吧?下面是具体的解决步骤:
1. 正确拆分独立模块的Schema与解析器
首先要把两个类型拆成独立的子Schema,每个模块只负责自己的类型和相关查询:
Referee模块(refereeSchema.js)
# 类型定义 type Referee { id: ID! stringProp: String! } type Query { referee(id: ID!): Referee }
对应的解析器:
const refereeResolvers = { Query: { referee: (_, { id }) => { // 模拟数据源,返回完整的Referee对象 return { id, stringProp: `Referee ${id}的属性` }; }, }, };
Referer模块(refererSchema.js)
# 类型定义,这里只声明依赖的Referee类型的骨架 type Referee { id: ID! } type Referer { id: ID! pointer: Referee! } type Query { referers: [Referer] }
对应的解析器:
const refererResolvers = { Query: { referers: () => { // 模拟数据源,返回仅含id和pointer.id的Referer列表 return [ { id: "ref1", pointer: { id: "referee1" } }, { id: "ref2", pointer: { id: "referee2" } }, ]; }, }, };
2. 配置Schema Stitching的类型合并与解析转发
核心是在合并Schema时,告诉Stitching系统如何处理跨模块的Referee类型,以及如何转发pointer字段的解析请求到Referee模块:
const { stitchSchemas } = require('@graphql-tools/stitch'); const { makeExecutableSchema } = require('@graphql-tools/schema'); // 生成子Schema const refereeSchema = makeExecutableSchema({ typeDefs: require('./refereeSchema').typeDefs, resolvers: refereeResolvers, }); const refererSchema = makeExecutableSchema({ typeDefs: require('./refererSchema').typeDefs, resolvers: refererResolvers, }); // 合并Schema并配置跨模块解析逻辑 const mergedSchema = stitchSchemas({ subschemas: [ { schema: refereeSchema, // 为Referee类型设置键,方便关联 merge: { Referee: { selectionSet: '{ id }', fieldName: 'referee', args: (originalObject) => ({ id: originalObject.id }), }, }, }, { schema: refererSchema, }, ], // 全局解析器:处理Referer的pointer字段,转发到Referee模块 resolvers: { Referer: { pointer: { selectionSet: '{ pointer { id } }', resolve(parent, args, context, info) { return info.mergeInfo.delegateToSchema({ schema: refereeSchema, operation: 'query', fieldName: 'referee', args: { id: parent.pointer.id }, context, info, }); }, }, }, }, });
3. 验证查询效果
现在你再执行之前的查询:
query FromStitchedSchema { referers { id pointer { id stringProp } } }
就能正确获取到pointer对应的stringProp属性了——Stitching系统会自动把Referer模块的pointer.id转发到Referee模块的referee查询,拿到完整的Referee对象。
关键注意点
- 子Schema中对于依赖的类型,只需要声明必要的标识字段(比如
id)即可,不需要重复定义完整字段 - 合并时的
merge配置是核心,它告诉Stitching如何根据标识字段获取完整的类型数据 - 跨模块字段的解析要使用
delegateToSchema来转发请求,确保数据从正确的模块获取
内容的提问来源于stack exchange,提问作者Tomas Aschan
相关产品推荐
相关产品推荐

