You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于GraphQL Schema Stitching,如何合并两个服务的查询结果为单个数组?

如何通过Schema Stitching合并两个GraphQL服务的查询结果?

当然可以实现。你需要在网关层为统一的search查询编写自定义解析器,同时调用两个子服务的_search接口,将返回结果合并后返回。

先明确各服务的Schema定义:

图书服务Schema

interface Searchable {
 id: ID!
} 

type Book implements Searchable {
  id: ID!
  name: String
  # 其他字段
}

type Query {
 _search( term: String ): [Searchable]
}

用户服务Schema

interface Searchable {
 id: ID!
} 

type Author implements Searchable {
  id: ID!
  name: String
  # 其他字段
}

type Query {
 _search( term: String ): [Searchable]
}

期望的网关Schema

interface Searchable {
 id: ID!
} 

type Book implements Searchable {
  id: ID!
  name: String
  # 其他字段
}

type Author implements Searchable {
  id: ID!
  name: String
  # 其他字段
}

type Query {
 search( term: String ): [Searchable]
}

实现步骤与代码示例

核心是利用@graphql-tools/stitch的自定义解析器能力,同时触发两个子服务的查询并合并结果:

  1. 导入子服务的远程Schema:先通过 introspect 获取两个子服务的Schema实例,并配置对应的执行器。
  2. 添加网关自定义查询与解析器:在合并Schema时,定义网关的search查询,并编写解析器逻辑。
import { stitchSchemas } from '@graphql-tools/stitch';
import { introspectSchema } from '@graphql-tools/wrap';
import { fetch } from 'cross-fetch';

// 创建远程服务的请求执行器
async function createRemoteExecutor(serviceUrl) {
  return async ({ document, variables }) => {
    const response = await fetch(serviceUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query: document, variables }),
    });
    return response.json();
  };
}

// 初始化图书服务的Schema与执行器
const bookServiceExecutor = createRemoteExecutor('http://your-book-service-url/graphql');
const bookServiceSchema = await introspectSchema(bookServiceExecutor);

// 初始化用户服务的Schema与执行器
const authorServiceExecutor = createRemoteExecutor('http://your-author-service-url/graphql');
const authorServiceSchema = await introspectSchema(authorServiceExecutor);

// 合并Schema并实现search查询的合并逻辑
const gatewaySchema = stitchSchemas({
  subschemas: [
    { schema: bookServiceSchema, executor: bookServiceExecutor },
    { schema: authorServiceSchema, executor: authorServiceExecutor },
  ],
  // 定义网关的自定义查询
  typeDefs: `
    extend type Query {
      search(term: String): [Searchable]
    }
  `,
  resolvers: {
    Query: {
      async search(_, { term }, context) {
        // 并行调用两个子服务的_search接口
        const [bookSearchResult, authorSearchResult] = await Promise.all([
          context.executors.get(bookServiceSchema)({
            document: '{ _search(term: $term) { __typename id name } }',
            variables: { term },
          }),
          context.executors.get(authorServiceSchema)({
            document: '{ _search(term: $term) { __typename id name } }',
            variables: { term },
          }),
        ]);

        // 合并两个服务的返回结果
        return [
          ...bookSearchResult.data._search,
          ...authorSearchResult.data._search
        ];
      },
    },
    // 确保接口类型解析正确(若自动解析有问题可手动指定)
    Searchable: {
      __resolveType(obj) {
        return obj.__typename;
      },
    },
  },
});

关键注意点

  • 两个子服务的Searchable接口结构必须完全一致,否则Schema合并时会抛出兼容性错误;
  • 查询时必须请求__typename字段,这样网关才能正确识别返回对象的具体类型,完成接口的类型解析;
  • 可根据业务需求添加错误处理逻辑,比如某个服务不可用时,返回另一个服务的结果,避免整体查询失败。

内容的提问来源于stack exchange,提问作者Jimish Fotariya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 15:20:37