Let's assume a type hierarchy of Customer -(hasMany)-> Orders -(hasMany)-> OrderLines
Something like this:
Customer {
Name
Orders [
{
OrderId
Date
OrderLines [
{
ItemCount
ItemName
}
]
}
]
}
I want to query for this whole tree, and filter on properties at any level in the tree.
For instance: Get all customers who ordered 'gizmos'.
This is what I tried: at each level of the hierarchy, I specify optional arguments that would filter based on the properties available at that level:
Customer (Name) {
Name
Orders (OrderId, Date) [
{
OrderId
Date
OrderLines (ItemCount, ItemName) [
{
ItemCount
ItemName
}
]
}
]
}
GraphQL needs me to define how to resolve each type in the hierarchy, so when resolving, I filter based on the arguments in the query.
But what if I only specify a filter at a deep level? e.g. ItemName : 'gizmo'
Assuming there's only one order line in the system containing a gizmo, I would expect to get a response like this:
[{
Name: "cust12",
Orders [{
OrderId: "ade32f",
OrderLines: [{
ItemCount: 50000, //customer really likes gizmos
ItemName: "gizmo"
}]
}]
}]
But what I actually get is all customers (no filter there), all their orders (no filter there) and all order items, mostly empty (the items inside are filtered).
[{
Name: "cust12",
Orders [
{
OrderId: "aaaaaa",
OrderLines: [ ]
},
{
OrderId: "ade32f",
OrderLines: [{
ItemCount: 50000,
ItemName: "gizmo"
}]
},
{
OrderId: "bbbbbb",
OrderLines: [ ]
},
{
OrderId: "cccccc",
OrderLines: [ ]
}
]
},
{
Name: "cust345",
Orders [
{
OrderId: "eeeeee",
OrderLines: [ ]
},
{
OrderId: "ffffff",
OrderLines: [ ]
}
]
}]
GraphQL calls the resolvers top-down: - get all (filtered) clients - for each of these get all (filtered) orders - for each of those get all (filtered) order lines
Because of the top-down nature of calling the resolvers, I get a lot more data than I bargained for.
How should I approach this?
Relation filters
This is actually a more complex topic than it first seems. The problem is that your current filter condition expresses
but what you really want is
get all customers that are related to at least one item named 'gizmo'
An elegant solution for this problem is the addition of relation filters to the schema. In your case, it could look like this:
Using
we only fetch customers that are indirectly related to an item named 'gizmo', exactly what we wanted.
Two more examples:
get all customers that are not related to any item named 'gizmo'
get all customers where all their orders contain some order line with an item named 'gizmo'
The
every
,some
andnone
relation filters are an essential part of the Graphcool APIs - you can read more here.