Graphql include directive - graphql

I have a query that takes a status as an input variable which is an enum of (future, past, all).
I'd like to return some fields only when the status is future. I've tried using #include but it seems it will only accept a boolean exactly.
Is there some way of getting this to work:
aField #include(if: $status == future)

I think you can't use even use boolean fields with #include - literals/query variables only, so expressions are a no-go as well.
If it's really important, and you're able to modify the API/schema, you could (ab)use the interface functionality - have future entities resolve to one type, and past entities to another, then you can use fragments to select fields based on which it is:
interface Competition {
id: ID!
name: String!
status: Status!
something: String
}
type FutureCompetition implements Competition {
// same fields
}
type PastCompetition implements Competition {
// same fields
}
Then you can query with something like this:
competitions {
id
name
status
... on FutureCompetition {
something
}
}
A possibly easier thing to do would be to simply do two queries in one and merge the results client-side, assuming you can query by status:
pastCompetitions: competitions(withStatus: PAST) {
id
name
status
}
futureCompetitions: competitions(withStatus: FUTURE) {
id
name
status
something
}

variables is a JSON. So, you can also try passing the status : inputStatus==='FUTURE' ? true : false

Related

Query GraphQL with multiple types

I'm trying to make a GraphQL query, out of the ordinary, but so far I haven't found anything related.
I would like to leave the where parameter with two optional types, see the example. Is this supported?
input Person {
name: String
email: String
}
input Company {
name: String
domain: String
}
type GetSearch {
name
email
domain
}
extend type Query {
getSearch(where: Person | Company): [GetSearch]
}
This is not possible.
Adding Input Union type to GraphQL was already proposed back in 2018, but it was never added. See this discussion for more details.

Passing variables in GraphQL

I'm trying to run a GraphQL query in the AWS AppSync console:
query MyQuery {
getUserInfoById(id: "1234566789") {
account {
id // need this value for getAvailableCourses
}
}
getAvailableCourses(accountId: "", pageNumber: 0) {
data {
id
name
type
}
}
}
Basically I need the value account.id in getUserInfoById for getAvailableCourses. I'm obviously new to GraphQL. How would I go about this?
To the best of my knowledge, there can be two ways you can do this.
You can handle this in your frontend by getting user's id
from the session info and pass it to the other query.
You can also merge these two queries and make it one. You will also have to change the respective fields. Then attach a resolver with AvailableCourses and use $ctx.source.id in the resolver to get further details. Schema would look something like this
type Account {
id : ID!
availableCourses: AvailableCourses
..
}
type AvailableCourses {
name: String!
type: String!
..
}
type Query {
getUserInfoById(id: ID!): Account
}
Using the returned fields as inputs for a second query into your datasource is precisely what field resolvers are for. I can't say for sure since I don't know your schema or access patterns but it looks like you need to make available courses a sub field of the user.

In GraphQL, can you change the structure of the output in an alias?

Let's say I've got a GraphQL query that looks like this:
query {
Todo {
label
is_completed
id
}
}
But the client that consumes the data from this query needs a data structure that's a bit different- e.g. a TypeScript interface like:
interface Todo {
title: string // "title" is just a different name for "label"
data: {
is_completed: boolean
id: number
}
}
It's easy enough to just use an alias to return label as title. But is there any way to make it return both is_completed and id under an alias called data?
There is no way to do that. Either change the schema to reflect the client's needs or transform the response after it is fetched on the client side.

How to approach a GraphQL query that returns a boolean value?

Need to check whether an email is available or taken during the user sign-up process. The goal is to quickly query, using GraphQL, the API server and have it tell us if the email is available or taken.
What is the general best practice on a simple boolean-ish type of situation using GraphQL?
Below is what I have come up with but I am unsure if this is a good practice or not and want to hear feedback on a better practice on queries like this.
Request:
query {
emailExists(email:"jane#doe.com") {
is
}
}
Response:
{
"data": {
"emailExists": {
"is": true
}
}
}
A "query" is just a field on what happens to be the Query type. A field can return any output type, including scalars -- it doesn't need to return an object. So it's sufficient to have a schema like:
type Query {
emailExists(email: String!): Boolean!
}
The only reason to prefer an object type would be if you anticipated wanting to add additional fields in the future (i.e. something other than your current is field).

GraphQL: Are either of these two patterns better/worse?

I'm relatively new to GraphQL, and I've noticed that you can select related fields in one of two different ways. Let's say we have a droids table and a humans table, and droids have an owner which is a record in the humans table. There's (at least) two ways you can express this:
query DroidsQuery {
id
name
owner {
id
}
}
or:
query DroidsQuery {
id
name
ownerId # this resolves to owner.id
}
At first glance the former seems more idiomatic, and obviously if you're selecting multiple fields it has advantages (owner { id name } vs. having to make a new ownerName so you can do ownerId ownerName). However, there's a certain explicitness to the ownerId style, as you're expressing "here's this thing I specifically expected you to select".
Also, from an implementation standpoint, it seems like owner { id } would lend itself to the resolver making an unnecessary JOIN, as it would translate owner { id } as the id column of the humans table (vs. an ownerId field which, with its own resolver, knows it doesn't need a JOIN to get the owner_id column of the droids table).
As I said, I'm new to GraphQL, so I'm sure there's plenty of nuances to this question that I'd appreciate if I'd been using it longer. Therefore, I was hoping for insight from someone who has used GraphQL into the upsides/downsides of either approach. And just to be clear (and to avoid having this answer closed) I'm looking for explicit "here's what is objectively bad/good about one approach over the other", not subjective "I prefer one approach" answers.
You should understand GraphQL is just a query language + execution semantics. There are no restrictions on how you present your data and how you resolve your data.
Nothing stops you from doing what you describe, and returning both owner object and ownerId.
type Droid {
id: ID!
name: String!
owner: Human! # use it when you want to expand owner detail
ownerId: ID! # use it when you just want to get id of owner
}
You already pointed out the main problem: the former implementation seems more idiomatic. No you don't make a idiomatic code, you make practical code.
A real world example as you design field pagination in GraphQL:
type Droid {
id: ID!
name: String!
friends(first: Int, after: String): [Human]
}
The first time, you query a droid + friends, and it is fine.
{
query DroidsQuery {
id
name
friends(first: 2) {
name
}
}
}
Then, you click more to load more friends; it hits DroidsQuery one more time to query the previous droid object before resolving the next friends:
{
query DroidsQuery {
id
friends(first: 2, after: "dfasdf") {
name
}
}
}
So it is practical to have another DroidFriendsQuery query to directly resolve friends from droid id.

Resources