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

如何在GraphQL联邦架构中获取物料的区域特定库存信息?

GraphQL联邦架构中库存字段上下文匹配问题

当前架构定义

1. 区域服务(Zone Service)

扩展Material类型并关联区域,类型定义:

extend type Material @key(fields: "id") {
  id: ID! @external
}

type Zone @key(fields: "id") {
  id: ID!
  name: String!
  materials: [Material!]!
}

type Query {
  zones: [Zone!]!
}

2. 物料服务(Material Service)

提供物料基础信息:

type Material @key(fields: "id") {
  id: ID!
  name: String!
}

type Query {
  materials: [Material!]!
}

3. 库存服务(Stock Service)

扩展Material类型添加库存字段,库存数据关联物料ID和区域ID:

extend type Material @key(fields: "id") {
  id: ID! @external
  stocks: Stock!
}

type Stock {
  amount: Int!
}

type Query {
  stocks: [Stock!]!
}

库存数据集:

const stocks = [
  { id: "1", zoneId: "1", materialId: "1", amount: 100 },
  { id: "2", zoneId: "1", materialId: "2", amount: 50 },
  { id: "3", zoneId: "2", materialId: "2", amount: 80 },
  { id: "4", zoneId: "2", materialId: "3", amount: 120 },
];

查询需求与问题

执行以下查询时,期望每个区域下的物料返回对应区域的库存数据:

query Zones {
  zones {
    id
    name
    materials {
      id
      name
      stocks {
        amount
      }
    }
  }
}

问题:库存字段未结合区域ID(zoneId)返回匹配数据,比如区域B中物料Gravel的库存应为80,但实际返回了50(属于区域A的库存)。

解决方案

核心问题是当前Material.stocks字段仅能获取物料ID,无法拿到当前所在的区域上下文,需通过调整架构传递区域ID信息来解决:

方案1:通过实体扩展传递区域上下文

  1. 修改Zone Service的Material扩展,新增zoneId字段传递当前区域ID:
extend type Material @key(fields: "id") {
  id: ID! @external
  zoneId: ID! @external # 添加该字段,传递区域上下文
}

type Zone @key(fields: "id") {
  id: ID!
  name: String!
  materials: [Material!]! # 该字段的resolver需为每个Material注入zoneId
}
  1. 修改Stock Service的Material扩展,声明依赖zoneId字段解析库存:
extend type Material @key(fields: "id") {
  id: ID! @external
  zoneId: ID! @external # 接收Zone服务传递的区域ID
  stocks: Stock! @requires(fields: "zoneId") # 声明需要zoneId字段
}

type Stock {
  amount: Int!
}
  1. 在Stock服务的stocks resolver中,同时用物料ID和区域ID过滤数据:
// Stock服务的resolver示例
const resolvers = {
  Material: {
    stocks: (material) => {
      return stocks.find(stock => 
        stock.materialId === material.id && stock.zoneId === material.zoneId
      );
    }
  }
};

方案2:重新设计实体关联(贴合业务语义)

如果库存本身是区域与物料的关联实体,可定义中间实体明确三者关系:

  1. 在Zone Service中定义ZoneMaterial实体:
type ZoneMaterial @key(fields: "zoneId materialId") {
  zoneId: ID!
  materialId: ID!
  material: Material! @external
  stock: Stock!
}

type Zone @key(fields: "id") {
  id: ID!
  name: String!
  zoneMaterials: [ZoneMaterial!]!
}
  1. Stock服务扩展ZoneMaterial实体提供库存数据:
extend type ZoneMaterial @key(fields: "zoneId materialId") {
  zoneId: ID! @external
  materialId: ID! @external
  stock: Stock!
}

type Stock {
  amount: Int!
}

这种方式更清晰表达“区域-物料-库存”的关联关系,查询时可直接通过zoneMaterials获取对应维度的库存。

关键说明

  • GraphQL联邦中,实体字段的解析依赖父级传递的上下文数据,多维度过滤时需确保所需上下文字段(如zoneId)能通过实体扩展传递到对应服务。
  • @requires指令用于声明解析字段依赖的外部字段,网关会自动收集并传递这些字段给对应服务的resolver。

内容的提问来源于stack exchange,提问作者Krister Johansson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:57:14