Avoid using has at root. This will make a pretty wide lookup.
Your example is kind of confusing, try to humanize it. For example, what would generally be B? a product? Who would be A and C? buyer characteristics to compare?
This is only selecting nodes from B2 and throwing out the ones that are not in the filter based on B1.
This query would be more or less what I understood from your enunciate.
{
root(func: eq(myType, "Target B")) @cascade {
name
<~property_of> @filter(eq(name, "Target A")) {
name
}
realizes @filter(eq(name, "Target C")) {
name
}
}
}
Let me explain; The target is B(several B). And then we expand a reverse query and a forward one. Using the parameters that you demonstrate in your query. It could be anything.
End then I use Cascade directive. Stating that I only want answers where all values are True.
Using query with cascade you provided, it still take too much time, because I don’t have any filter on B.
I change my query to as the following:
{
root(func: eq(name, "Target A")) @cascade {
property_of{
B as uid
realizes @filter(eq(name, "Target C")) {
name
}
}
}
process(func: uid(B)) {
other_properties{
uid
name
}
}
}
I removed “has(name)” at root, and it’s much faster (from 10ms to 3ms).
But cascade does’t have effect the variable B in the following sub-query “process”, and process got many unwanted result.
Does cascade not have effect on variables? or on filters?
If I want to use variable B for other sub-queries, is there any good solutions to do that?
{
root(func: eq(name, "Target A")) @cascade {
B as property_of{
realizes @filter(eq(name, "Target C")) {
name
}
}
}
process(func: uid(B)) {
other_properties{
uid
name
}
}
}
Can you create a meaning? If you have a meaning, close to the real modeling you are creating. That would help a lot to give you a better solution. If I know what is A, B and C. I could suggest several ways of doing it.
A good example could be cities. You have a tree. Which has the country, the states and the cities. And you want to find a state that is in the US and has cities called “Springfield”. You will find (using this same structure that we are using) the states of Illinois and Oregon. get it?
e.g.
{
var(func: eq(name, "United States")) @cascade {
name
State as child {
name
city as child @filter(eq(name, "Springfield")) {
name
}
}
}
States(func: uid(State)) {
name #state name || Illinois and Oregon will be here
child @filter(uid(city)){
uid
name #city name
}
}
}
As the B is supposed to be the real target here, we should filter it first. Unless from root/parent to B has less connections.
The principal in a query will always be Root. It is it who will decide the performance. Because that’s where we can reduce the memory/CPU footprint. If Target A, points to everyone. it will be forced to read everyone and that will take time. B has no influence as it is being reduced by Root. get it?
Root should already be a limiter/filter. If it’s taking a while, it’s because Root/parent has thousands of objects/nodes to lookup. Cuz it is a “pointer”. Edges are like indexes. You need to look for ways to further reduce it at the root query with filters or a better Graph Modeling strategy.