GraphQL: Connected filter on non-scalar list element fields

Consider the following schema:

type User {
   posts: [Post!] 
}

type Post {
   content: String!
   reactions: [Reaction!]
}

type Reaction {
   type: String!
   user: User!
}

I want to query for a user and filter for his/her posts where the reaction list contains at least a reaction of type “thumbs_up” AND a reaction of type “clap”, such that I receive the full list of reactions for posts that match this nested filter (ie. cascading with a filter on reaction type does not work).

This is likely relate closely to - and might be resolved by - the following proposals, but I’m not positive…(@chewxy?)


There are other list filters that would be immediately useful to me as well…length primarily.

1 Like

I agree with you that this is something that cannot currently be done in a single query with GraphQL. The cascade directive does not solve this use case because you are wanting a AND filter on a child and cascade would only make sure that there is a child not that there are children of each type. A way around this in GraphQL currently would be to use cascade with alias edges. Create an alias for each child that must be included.

However, we currently solve this problem with filtering using deep logic by using DQL (New to DQL?). With DQL, we can create multiple var blocks and then use logic to get resulting nodes by mixing those var blocks.

Isn’t @auth still a problem with DQL?

If by problem you mean that the @auth directive is not supported in DQL and all auth rules are completely ignored when running DQL queries and mutations, then yes.

Our work around for this is to use DQL to get a list of uids that fullfill the filter parameters and then with those uids, get the data using GraphQL.

When there is a will, there is a way :wink: I am all for making my work arounds not needed, but it is just how we learned to cope with some of the limitations in the meantime.

1 Like

Hey @CosmicPangolin1

While we are looking into how could we make this possible, can you share an example of what result do you expect given a dataset? We can possibly look into supporting this in the next quarter once we know what you are looking for?

@pawan Sorry about the delay…I might be able to best illustrate with query examples (which may or may not be accurate in their own right, so correct me if need be).

Query 1

getUser {
   posts @cascade {
      content
      reactions(filter: {
         type: {in: ["thumbs_up", "clap"]}
      }){
         type
         user {name}
      }
   }
}

I think this query gets me only posts that have either thumbs up OR clap reactions. I believe it also sorts out reactions that don’t match the filter.

Query 2

getUser {
   posts @cascade {
      content
      reactions(filter: {type: {eq: "thumbs_up"}}, or: {type: {eq: "clap"}}) {
         type
         user {name}
      }
   }
}

I think this query gets me the same thing as the first.

Query 3

getUser {
   posts @cascade {
      content
      reactions(filter: {type: {eq: "thumbs_up"}}, and: {type: {eq: "clap"}}) {
         type
         user {name}
      }
   }
}

This wouldn’t return anything since the rules are mutually exclusive (as are the values).

So what I want is (I think) is a new input type on connected sets for contains/includes functionality, so I can build a query similar to Query 1 in that it filters for posts with thumbs_up AND/OR clap reactions, but additionally returns all reactions.

The idea is that we often want to have cascading filters on computed properties of a connected set (contains, length, and every are the generic List methods that come to mind), the same way we do for values of singular fields. In my use case, I might have many posts with claps and many posts with thumbs_ups, but only a few with both that I want to retrieve for a client. The functionally equivalent block would be something like:

if (arr.contains((reaction) => reaction.type == "clap") && arr.contains((reaction) => reaction.type == "thumbs_up")) {
   return arr;
}

It might look something like this:

getUser {
   posts @cascade {
      content
      reactions(contains: {type: {eq: "thumbs_up"}}, 
         and/or: {contains: {type: {eq: "clap"}}}
      ) {
         type
         user {name}
      }
   }
}

Hey @CosmicPangolin1

Can you please share a small data set on which I can run this query and the JSON result that you expect this query to run? I think what you are asking for is possible (by Query 3 you mentioned above) but maybe I am missing something.