Dgraph graphql cascade and first

I was wondering if this is a bug or I am using it incorrectly.
I have the following graphql query,
which I am trying to get all accounts with a client name like ben and limit those results to 10.
But it seems like the below is getting the top 10 accounts and then cascading via client name.
So if I have a large list of accounts, the query rarely returns the results I want. I know in this simple example I can invert the query, but I have more complex examples with other filters/multiple cascade filtering.

query {
  queryAccount(first:10, offset:0) @cascade {
    id
    client(filter:{name:{regexp:"/.*ben.*/"}}) {
      name
    }
  }
}
2 Likes

Just to provide some examples, this also happens in DQL.

Here is an example GraphQL Schema:

GraphQL Schema
type Upper {
    id: ID!
    name: String @search(by: [regexp])	
    lowers: [Lower] @hasInverse(field: upper)
}

type Lower {
    id: ID!
    name: String @search(by: [regexp])
    upper: Upper @hasInverse(field: lowers)
}

and here is some example data to use with the liveloader feature:

RDF Data
<_:a1>   <dgraph.type> "Upper" .
<_:a1>   <Upper.name> "Upper 1" .

<_:xb>   <dgraph.type> "Lower" .
<_:xb>   <Lower.name> "Lower ab" .
<_:xb>   <Lower.upper> <_:a1> .
<_:a1>   <Upper.lowers> <_:xb> .

<_:a2>   <dgraph.type> "Upper" .
<_:a2>   <Upper.name> "Upper 2" .

<_:xc>   <dgraph.type> "Lower" .
<_:xc>   <Lower.name> "Lower abc" .
<_:xc>   <Lower.upper> <_:a2> .
<_:a2>   <Upper.lowers> <_:xc> .

<_:a3>   <dgraph.type> "Upper" .
<_:a3>   <Upper.name> "Upper 3" .

<_:xd>   <dgraph.type> "Lower" .
<_:xd>   <Lower.name> "Lower abcd" .
<_:xd>   <Lower.upper> <_:a3> .
<_:a3>   <Upper.lowers> <_:xd> .

<_:a4>   <dgraph.type> "Upper" .
<_:a4>   <Upper.name> "Upper 4" .

<_:xe>   <dgraph.type> "Lower" .
<_:xe>   <Lower.name> "Lower bdef" .
<_:xe>   <Lower.upper> <_:a4> .
<_:a4>   <Upper.lowers> <_:xe> .

<_:a5>   <dgraph.type> "Upper" .
<_:a5>   <Upper.name> "Upper 5" .

<_:xf>   <dgraph.type> "Lower" .
<_:xf>   <Lower.name> "Lower efg" .
<_:xf>   <Lower.upper> <_:a5> .
<_:a5>   <Upper.lowers> <_:xf> .

If you apply the schema, then load the data, you should be able to run the following DQL query, where we expect 2 results, but only get 1:

{
  q(func: eq(dgraph.type,"Upper"), first:2) @cascade {
    uid
    Upper.name
    Upper.lowers @filter(regexp(Lower.name, /.*a.*/)) {
      uid
      Lower.name
    }
  }
}

Same result if we query this using GraphQL (expect 2, get 1):

query {
  queryUpper(first:2, offset:0) @cascade {
    id
    lowers(filter:{name:{regexp:"/.*a.*/"}}) {
      id
      name
    }
  }
}

Just through some further research, it appears that there may be other related issues, however, to illustrate our point, we feel that given the following GraphQL (ignoring @auth rules):

query {
  queryAccount(first:10, offset:0) @cascade {
    id
    client(filter:{name:{regexp:"/.*ben.*/"}}) {
      name
    }
  }
}

we are really attempting to get the same result as this DQL:

{
  var (func: type(Client)) @filter(regexp(Client.name, /.*ben.*/)) @cascade {
    Client.accounts {
      var flt1 as uid
    }
  }
  
  accounts(func: type(Account), first: 10) @filter(uid(flt1)) {
    uid
    Account.name
  }
}

This request should ensure that we get any clients where the name is ‘like’ “%ben%”, ensuring that those clients returned have at least 1 account, then using the returned client uids, we can filter the accounts to get the top 10 that match.

We’d use the DQL, but it doesn’t respect the @auth directive rules from the GQL Schema.

1 Like

This is a known issue. This happens because @cascade is a post-processing step.

We are actively working on fixing this.

Related Discuss Posts:

  1. Cascade Directive with Pagination produces unexpected results
  2. Cascade does not work with pagination

Related RFC: WIP: cascade with pagination

2 Likes