I have two microservices ms1 and ms2 that output different types of data each time an API gateway built with Apollo GraphQL sends requests through resolvers.
To be specific, the first resolver getCart(userId: ID!): Cart!
calls ms1 and it responds it with the following response body:
{
"items": [
{
"itemId": "8a016af8-5336-4799-b806-73976996aa6f",
"quantity": 1
},
{
"itemId": "9a016af8-5336-4799-b806-73976996aa6f",
"quantity": 2
}
]
}
That is, the Cart
type, just an object containing an array of items with id and quantity.
The second resolver getItem(itemId: ID!): Item!
calls ms2 and it responds it with the following response body:
{
"itemId": "7a016af8-5336-4b99-b806-73976996aadf",
"name": "Jack Daniel's Blue Label",
"price": 29.99
}
Is there any way to "combine" or sequence these two queries directly from a frontend (e.g. Apollo Sandbox or GraphiQL) in such a way that I get the following response?
{
"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
}
]
}
In pseudo-graphql I was thinking about something like this:
query GetCartInfo($userId: ID!) {
getCart(userId: $userId) {
items {
itemId => getItem(itemId: $itemId) {
name
price
}
quantity
}
}
}
If that’s not possible, what would be the best way to achieve this? Create a new resolver in the API gateway? Modify the array from another service in the frontend?
Thanks for the help and information about the topic, I would really appreciate it 😀
Have a nice day!
3
Answers
You can possibly use GraphQL’s field resolvers, which allow defining custom logic to resolve fields in a GraphQL query.
In the API gateway, you can create a new resolver that resolves the items field in the getCart query. Here is a rough example:
I hope this will help.
The best way would be to do this not on the client, but on the server by using a Gateway or Federation Router service in front of your microservices that stitches both of these
Item
entities into one and answers your query forItem
with only one query from the client, but answers from both microservices.One way of doing that would be Apollo Federation. You can read up on that here.
You can’t do this from the client, you need to modify the GraphQL schema and your resolvers.
In your schema you should have a
Cart
type and anItem
type and also aCartItem
type to deal with quantities.Given this structure, your query:
Should be able to be called with:
Your
getCart
query resolver needs to invokesms1
to get the the list ofCartItem
s and then, like @orabis suggests, yourCartItem
type needs a resolver for theitem
field that invokesms2
. GraphQL will automatically combine the results of the query resolver with the field resolver.The response should look like:
I should add that if this query is to be done by the user who owns the cart then for security the user’s
id
should not be a parameter to the query. The user’sid
should be provided by thecontext
parameter to the query resolver.