json 如何对GraphQL查询进行排序以输出相互依赖的数据?

rvpgvaaj  于 2023-05-08  发布在  其他
关注(0)|答案(1)|浏览(169)

我有两个微服务ms 1ms 2,每次使用Apollo GraphQL构建的API网关通过解析器发送请求时,它们都会输出不同类型的数据。
具体来说,第一个解析器getCart(userId: ID!): Cart!调用ms 1,并使用以下响应体进行响应:

{
  "items": [
    {
      "itemId": "8a016af8-5336-4799-b806-73976996aa6f",
      "quantity": 1
    },
    {
      "itemId": "9a016af8-5336-4799-b806-73976996aa6f",
      "quantity": 2
    }
  ]
}

也就是说,Cart类型,只是一个包含一个具有id和数量的项目数组的对象。
第二个解析器getItem(itemId: ID!): Item!调用ms 2,并使用以下响应体进行响应:

{
  "itemId": "7a016af8-5336-4b99-b806-73976996aadf",
  "name": "Jack Daniel's Blue Label",
  "price": 29.99
}

是否有任何方法可以直接从前端“合并”或排序这两个查询(例如Apollo Sandbox或GraphiQL),这样我会得到以下响应?

{
  "items": [
    {
      "itemId": "8a016af8-5336-4799-b806-73976996aa6f",
      "name": "Jack Daniel's - Honey",
      "price": 19.99,
      "quantity": 1
    },
    {
      "itemId": "7a016af8-5336-4799-b806-73976996aa6f",
      "name": "Jack Daniel's - Red Label",
      "price": 29.99,
      "quantity": 2
    }
  ]
}

在pseudo-graphql中,我想到了这样的东西:

query GetCartInfo($userId: ID!) { 
  getCart(userId: $userId) {
    items {
      itemId => getItem(itemId: $itemId) {
        name
        price
      }
      quantity
    }
  }
}

如果这是不可能的,那么实现这一目标的最佳方法是什么?是否在API网关中创建新的解析程序?在前端从另一个服务修改阵列?
谢谢你的帮助和关于这个主题的信息,我真的很感激:D
祝你今天愉快!

cwxwcias

cwxwcias1#

您可以使用GraphQL的字段解析器,它允许定义自定义逻辑来解析GraphQL查询中的字段。
在API网关中,您可以创建一个新的解析器来解析getCart查询中的items字段。下面是一个粗略的例子:

const resolvers = {
  Query: {
    getCartInfo: async (_, { userId }) => {
      // Send a request to ms1 to get the cart data
      const cartData = await ms1API.getCart(userId);

      // Send a request to ms2 to get item details For each item
      const itemPromises = cartData.items.map(async (item) => {
        const itemDetails = await ms2API.getItem(item.itemId);
        return {
          itemId: item.itemId,
          name: itemDetails.name,
          price: itemDetails.price,
          quantity: item.quantity,
        };
      });

      const items = await Promise.all(itemPromises);

      return {
        items,
      };
    },
  },
};

我希望这会有所帮助。

相关问题