Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply a Hasura `where` filter only if a variable is not null?

Tags:

hasura

I have a query like this:

query getUsers ($setId: Int) {
  user(where: { user_sets: { set_id: { _in: [$setId] } } }) {
    id
    name
    status
    user_sets {
      set {
        name
      }
    }
    # more fields...
  }
}

What I'm looking for, is a way to not apply the where filter and give all entries if $setId is null. I'd like to avoid dynamically writing the query - it'd be easy to do something like this, but we want queries in static .graphql files:

const query = `
query getUsers (${ setId ? '$setId: Int' : ''}) {
  user(${ setId ? 'where: { user_sets: { set_id: { _in: [$setId] } } }' : '' }) {
`

Some things I've tried:

  • Using GraphQL directives like @skip and @include, but it seems these only apply to fields returned, not to any part of a where filter
  • Using Hasura boolExps like _is_null and _or, but it seems these can't test variables directly, they can only compare variables to columns contents
like image 695
user56reinstatemonica8 Avatar asked Apr 23 '19 11:04

user56reinstatemonica8


People also ask

How do you handle null values in GraphQL?

Nulls in the query A GraphQL query can have fields and inputs, with or without variables. Fields are always optional, whether nullable or not. In inputs, such as field arguments, nullable types are always optional and non‐null types are always required.

How do I return null in GraphQL?

Null is not a GraphQL type so to return null from a GraphQL mutation you have to return a GraphQL type that is nullable. All GraphQL types are nullable by default so you can just return a bool in the schema but return void from the implementation.

What is Hasura action?

What are Hasura Actions? ​ Actions are a way to extend Hasura's schema with custom business logic using custom queries and mutations. Actions can be added to Hasura to handle various use cases such as data validation, data enrichment from external sources and any other complex business logic.


2 Answers

This behaviour changed somewhere between v1.3.4. Therefore there are two correct answers.

You can read more about this change in the hasura repository.

Before Version 1.3.4

This answer describes it.

After Version 1.3.4

Using null in comparisons is dangerous when defaulting to true because an accidentally unset variable could result in a dropped table. The maintainers removed this behaviour but made it accessible by setting the variable HASURA_GRAPHQL_V1_BOOLEAN_NULL_COLLAPSE.

When comparing with {_eq: null} Hasura will throw an error, because it is assumed, that this is a mistake.

If you want to compare to a value and evaluate to true when the value is null you need to handle the case on the client site and passing the whole boolean expression to hasura.

query getUsers ($userSetsWhere: user_sets_bool_exp) {
  user(where: { user_sets: { $userSetsWhere } }) {
    id
    name
    status
    user_sets {
      set {
        name
      }
    }
    # more fields...
  }
}
const userSetsWhere = setId ? { set_id: { _eq: $setId } } : {};

What is does, is that only in case the value is not null or undefined a non-empty expression gets passed to hasura.

like image 123
Friedrich Avatar answered Sep 21 '22 19:09

Friedrich


You can use bool expressions as binding variables for such situations

query getUsers ($condition: user_bool_exp!) {
  user (where: $condition) {
    id
    name
    status
    user_sets {
      set {
        name
      }
    }
    # more fields...
  }
}

And you can build conditions depending on your variables

{ condition: { user_sets: { set_id: { _in: [$setId] } } } }

or

{ condition: { user_sets: {} }
like image 27
olegen Avatar answered Sep 21 '22 19:09

olegen