Cascade with variable Or nested Filter

Lets say I have a query as such:

query test($filterStudent: StudentFilter, $filterClass: ClassFilter, $filterRoom: RoomFilter) {
  queryStudent(filter: $filterStudent){
     id
     age
     firstName
     classes(filter: $filterClass) {
       id
       description
       room(filter: $filterRoom) {
         id
         name
      }
    }
  }
}

Now I want to filter all Students that have a specific Room.name.
If I just use the $filterRoom, I still get all the Students, but the not fitting rooms are removed from the result.
I know that I should use @cascade in that case. The issue here is, that some fields can be null, and I still would want them back. So a workaround here is to use the brandnew Parameterized @cascade (thanks for that :smiley:)

As I like to have more universal querys, It could also happen that I just want all Students, etc. So I can’t used a @cascade(fields: ["classes", "room"], thus I thought it would be nice to pass the cascade fields by variable or use a boolean to activate or deactivate the cascade (using @include)
Unfortunately even the use of variables is not supported, as the variable name is interpreted as text.

I’d imagine something like this:
does not work, fires the same as @cascade(fields: [])


query test($filterStudent: StudentFilter, $filterClass: ClassFilter, $filterRoom: RoomFilter, $cascade: String) {
  queryStudent(filter: $filterStudent) @cascade(fields: $cascade){
     id
     age
     firstName
     classes(filter: $filterClass) {
       id
       description
       room(filter: $filterRoom) {
         id
         name
      }
    }
  }
}

Can you post your schema? A schema and small example dataset if possible will help better reproduce the situation easily on other systems. Also, if you have an example of results received vs. results expected it helps other visualize the problem with less reading and comprehension.

This should technically be $cascade: [String], but even still, the GraphQL API should coerce the String into an array. So this is not the main point here.

Remember that any cascade will cascade down through all levels. If this was working with inputs, you would have most likely received the error:

Field room is not present in type Student. You can only use fields which are in type Student

You would have to use multiple cascade directives such as:

query test(
  $filterStudent: StudentFilter,
  $filterClass: ClassFilter,
  $filterRoom: RoomFilter,
  $cascadeStudent: [String] = ["id"]
  $cascadeClass: [String] = ["id"]
  $cascadeRoom: [String] = ["id"]
) {
  queryStudent(filter: $filterStudent) @cascade(fields: $cascadeStudent){
     id
     age
     firstName
     classes(filter: $filterClass) @cascade(fields: $cascadeClass) {
       id
       description
       room(filter: $filterRoom) @cascade(fields: $cascadeRoom) {
         id
         name
      }
    }
  }
}

But, nonetheless, it appears that the cascade directive inputs do not really accept variables? At least, I cannot get them to accept any variable in a few quick tests I did. I am gonna change this to a bug.

1 Like

As this is a simplified test example I have no real scheme at hand, but I constructed one for you. It would probably look like this:

type Student {
    id: String! @id
    age: DateTime @search
    firstName: String! @search(by: [term])
    classes: [Class!] @hasInverse(field: students)
}

type Class {
    id: String! @id
    description: String! @search(by: [term])
    students: [Student!]!
    room: Room!
}

type Room {
    id: String! @id
    name: String! @search(by: [term])
    classes: [Class!] @hasInverse(field: room)
}

for the dataset you could populate it with this query

mutation addData($input: [AddStudentInput!]!) {
  addStudent(input: $input) {
    student {
      id
      age
      firstName
      classes {
        id
        description
        room {
          id
          name
        }
      }
    }
  }
}
and these variables
  "input": [
    {
    "id": "student1",
    "firstName": "John",
    "classes": [
      {
        "id": "class1", 
        "description": "Math",
        "room":  {
          "id": "room1", 
          "name": "501"
        }
      },{
        "id": "class2", 
        "description": "English",
        "room":  {
          "id": "room2", 
          "name": "502"
        }
      }
    ]
    },
    {
    "id": "student2",
    "firstName": "Tim",
    "classes": [
      {
        "id": "class1", 
        "description": "Math",
        "room":  {
          "id": "room1", 
          "name": "501"
        }
      }
    ]
    },{
    "id": "student3",
    "firstName": "Simon",
    "classes": []
  }
  ]
}
1 Like

Hi @jlnrrg, this looks like a bug to me. Variable passed to @cascade should not be treated as text, it’s happening because the argument for cascade is of type [String].
Thanks for reporting this bug, Accepting it and will change this behavior soon.

1 Like

fix for the above issue is merged in master. We now support passing cascade arguments as variables.
PR: fix(GraphQL): Added support for parameterized cascade with variables. by JatinDevDG · Pull Request #7477 · dgraph-io/dgraph · GitHub

1 Like