Getting access to resolved entities in a Subgraph

So in Federation I could have a type that contains a field of entities resolved in another subgraph using an id as the key. Something like this

'''
resolved in another subgraph
'''
type Entity @key(fields: id) {
    id: ID!
}

type Something {
    id: ID!
    field: [Entity!]
    field2: SomeType!
}

My understanding is that the gateway will send my subgraph the request for this data, I will resolve all that I can, send it back to the gateway and then the gateway will take the keys it needs and go to the other subgraph to resolve the entities. The gateway will handle all the stitching of the data and my subgraph will never see that array.

Now lets say the array of entities is a list of products. I don’t want any products in that list to be sent back if they are out of stock. This, stock level, is part of the information that makes up the entity in its subgraph where it is resolved. As I never see those entities in my subgraph I can’t do any filtering to remove those products with no stock. I could do a call in my subgraph directly to the API responsable for resolving those entities with the ID and remove the IDs of products with no stock but then I have increased the number of calls I am making to that service. Is there anyway I could get the resolved entities back into my subgraph from the gateway so I can filter them, or is this just not supported like that?

If I understand correctly, the challenge here is that Subgraph A knows all products (by ID) that belong in the list, but only Subgraph B knows whether each of those products is in stock. To generate the final, filtered list, both pieces of information are required. I think the only way forward would be to generate two lists, one filtered, and one not. You could do something like this:

# Subgraph A
type Product @key(fields: "id") {
  id: ID!
}

type Something @key(fields: "id") {
  id: ID!
  allProducts: [Product!] @inaccessible
}
# Subgraph B
type Product @key(fields: "id") {
    id: ID!
    inStock: Boolean
}

type Something @key(fields: "id") {
  id: ID!
  allProducts: [Product!] @external
  products: [Product!] @requires(fields: "allProducts {id}")
}

Then, in the reference resolver for Something in Subgraph B, you get the inStock value for all the ids of allProducts and use that to filter the list, setting the products field.

This should only require one call to each subgraph—first to A to get allProducts, then to B to get products. The only catch is if there are more fields on the Product type elsewhere that would need to be re-resolved. You could work around that by using @provides, though.

Also worth noting, allProducts could be just a list of IDs, as well, if there aren’t other entity fields that are needed at that stage.

2 Likes