I have a product and items
Product:
{
id: Int
style_id: Int
items: [items]
}
Items:
{
id: Int
product_id: Int
size: String
}
I want to query products but only get back products that have an item with a size.
So a query could look like this:
products(size: ["S","M"]) {
id
style_id
items(size: ["S","M"]) {
id
size
}
}
But it seems like there should be a way where I can just do
products {
id
style_id
items(size: ["S","M"]) {
id
size
}
}
And in the resolver for the products I can grab arguments from the nested query and use them. In this case add the check to only return products that have those sizes. This way I have the top level returned with pagination correct instead of a lot of empty products.
Is this possible or atleast doing it the other way around:
products(size: ["S","M"]) {
id
style_id
items {
id
size
}
}
And sending the size argument down to the items resolver? Only way I know would be through context but the one place I found this they said that it is not a great idea because context spans the full query in all depths.
I agree with @DenisCappelini's answer. If possible, you can create a new type which represents only Products that have an Item.
However, if you don't want to do that, or if you're just interested in general about how a top-level selector can know about arguments on child selectors, here is a way to do that:
There are 2 ways to do it.
To do this:
products {
id
style_id
items(size: ["S","M"]) {
id
size
}
}
In graphql, resolvers have this signature:
(obj, args, context, info) => {}
The 4th argument, info
, contains information about the entire request. Namely, it knows about arguments on the child selectors.
Use this package, or a similar one because there are others, to parse info for you: https://www.npmjs.com/package/graphql-parse-resolve-info
The above is quite a lot of work, so if you want to do this instead:
products(size: ["S","M"]) {
id
style_id
items {
id
size
}
}
Then in your resolver for products
, you need to also return size
.
Suppose this is your resolver for products
:
(parent, args) => {
...
return {
id: '',
style_id: ''
}
}
Modify your resolver to also return size like this:
(parent, args) => {
...
return {
id: '',
style_id: '',
size: ["S", "M"]
}
}
Now in your resolve for products.items
, you will have access to the size
, like this:
(product, args) => {
const size = product.size
}