Conditional field in GraphQL Where query - graphql

Using Apollo client I am trying to run a query that will return students with any status if the status field is empty. If there is a status filter it should be applied:
const statusWhere = inputs.status ? { equals: $inputs.status }: {};
query GetStudents($course: ID, $status: String, $statusWhere: status_bool_exp) {
studentCourses (where :{
status: {$statusWhere},
course: {
id: {
equals: $course
}
},
# other fields, etc
This is giving error:
GraphQLError: Syntax Error: Expected Name, found "$".
Could you provide any hints?

After a bunch of trial and error I was able to figure it out myself. Posting it here because it could be useful for someone else.
Using the regular JS string interpolation variables works here.
So you need to define the condition as a string literal:
const statusWhere = inputs.status ? 'equals: "'+ inputs.status +'"' : '';
Then the whole gpl string looks like this:
gql`
query GetStudents($course: ID) {
studentCourses (where :{
status: {
${statusWhere}
},
course: {
id: {
equals: $course
}
},
})
# fields etc`
In this case you do not need to pass your string variable as a query param.

Related

How to pass object type argument in query in GraphQL?

I got this type of query
query {
searchRandom (param : MyObjectClass){
city
}
}
How may I set param with the type of MyObjectClass and pass it in the query? To be able to test here?
Use the following query.
query getData($param: MyObjectClass){
searchRandom(param: $param)
city
}
And then go to query variables tab in Graphiql and pass the variable data like this. You have not mention the data types included in MyObjectClass. So use this as an example:
{
"param": {"country": "England", "population": "High" }
}
Then the data should be returned as expected.
--- Additionally ---
If you are running the server, make sure you have set the followings.
You need to create a input object in the GraphQL schema.
input MyObjectClass {
country: String
population: String
}
Then in the resolver you have to pass the object as the argument. (Assuming you are using JavaScript)
const resolvers = {
Query: {
searchRandom: (parent, { param }) => {
var query_data = param
...//your code
return city_name;
},
},
I am not sure whether this addresses your question or not. I hope this answer helps though.

Can I make variables optional in a GraphQL query?

I have a query that includes a variable $filter which is a string.
This variable is only relevant if the user has said they want to filter the results. If user doesn't filter, I want all results back that meet the criteria.
Is there a way to omit the filter variable in this query? I've tried passing null and I get an error.
const NOTIFY_NEW_PUBLIC_FEELINGS = gql`
subscription notifyNewPublicFeelings($page_id: uuid!, $filter: String!) {
feelings(
where: { is_public: { _eq: true }, page_id: {_eq: $page_id}, feeling: {_eq: $filter} }
limit: 1
order_by: { created_at: desc }
) {
id
created_at
}
}
`;
The problem is that you've marked $filter as String! (! indicates non-nullable). So, necessarily, passing null is going to cause an issue. If you mark string as nullable (just String, without the !), you can pass null safely.

I get a GraphQL error when running this query using the apollo server. Anyone one knows what is the problem with it?

I am trying to fetch some data from the GitHub GraphQL but I get a GaphQLError. I have tried the same query on the developer section of github and it works. Anyone know what is the problem with it?
issueQuery = gql`
query search(first: 10, type: ISSUE, query: "repo:angular/angular is:issue state:open") {
issueCount
edges {
node {
... on Issue {
createdAt
title
body
url
comments(first: 10) {
nodes {
body
}
}
}
}
}
}
`;
Error Stack Trace:
"GraphQLError: Syntax Error: Expected $, found Name "first"
at syntaxError (http://localhost:4200/vendor.js:70270:10)
at expect (http://localhost:4200/vendor.js:75154:67)
at parseVariable (http://localhost:4200/vendor.js:73984:3)
at parseVariableDefinition (http://localhost:4200/vendor.js:73970:15)
at many (http://localhost:4200/vendor.js:75222:16)
at parseVariableDefinitions (http://localhost:4200/vendor.js:73959:82)
at parseOperationDefinition (http://localhost:4200/vendor.js:73926:26)
at parseExecutableDefinition (http://localhost:4200/vendor.js:73881:16)
at parseDefinition (http://localhost:4200/vendor.js:73845:16)
at many (http://localhost:4200/vendor.js:75222:16)"
New Error Stack Trace when adding $ before the parameters:
"GraphQLError: Syntax Error: Expected Name, found Int "10"
at syntaxError (http://localhost:4200/vendor.js:70270:10)
at expect (http://localhost:4200/vendor.js:75154:67)
at parseName (http://localhost:4200/vendor.js:73809:15)
at parseNamedType (http://localhost:4200/vendor.js:74385:11)
at parseTypeReference (http://localhost:4200/vendor.js:74364:12)
at parseVariableDefinition (http://localhost:4200/vendor.js:73971:83)
at many (http://localhost:4200/vendor.js:75222:16)
at parseVariableDefinitions (http://localhost:4200/vendor.js:73959:82)
at parseOperationDefinition (http://localhost:4200/vendor.js:73926:26)
at parseExecutableDefinition (http://localhost:4200/vendor.js:73881:16)"
Don't confuse the operation with the actual field being queried. The syntax should look like this:
operationType [operationName] [variableDefinitions] {
selectionSet
}
where operationType is one of query, mutation or subscription, operationName is an arbitrary name for your operation used in debugging, variableDefinitions are type definitions for any variables you reference inside the operation, and selectionSet is one or more fields you're actually querying.
In this case, search is a field we're querying, so it should not be proceeded by the query keyword. This works fine, provided you're authenticated:
query OptionalName {
search(first: 10, type: ISSUE, query: "repo:angular/angular is:issue state:open") {
issueCount
edges {
# more fields
}
}
}
If the operation type is query, you can omit the query keyword altogether. This is called "query shorthand":
{
search(first: 10, type: ISSUE, query: "repo:angular/angular is:issue state:open") {
issueCount
edges {
# more fields
}
}
}
If you use variables, define them inside parentheses beside your operation. Variable names are arbitrary, but by convention we use the input field names they will be used in:
query OptionalName ($first: Int, type: SearchType!, $query: String! ) {
search(first: $first, type: $type, query: $query) {
issueCount
edges {
# more fields
}
}
}

Apollo graphql queries with type condition on nested fields

I am working on the following types, where the "content" of a "Comment" is a union type:
type TextContent {
text: String
}
type RichContent {
participants: [String]
startTime: String
}
union Content = TextContent | RichContent
type Comment {
id: ID
sender: String
content: Content
}
type Review {
id: ID
title: String
lastComment: Comment
}
In my Apollo query, I was trying to use conditional fragments on the 2 Content types:
query listOfReviews {
reviews {
...reviewFields
}
}
fragment reviewFields on Review {
id
title
lastComment {
content {
... on TextContent {
text
}
... on RichContent {
participants
startTime
}
}
}
}
I received a runtime error where Apollo seems trying to access "participants" field of "undefined", where the actual content object is:
{
__typename: "TextContent:,
text: "abc"
}
It looks the two types of the union Content are merged together.
My question is: is it allowed to use type conditions on nested fields in Apollo queries? Or type conditions have to be used on the top level types returned by the queries? If it's allowed, how should I fix my types/queries?
Thanks a lot!
#const86 helped point out that this is due to this bug: https://github.com/apollographql/apollo-link-state/pull/258.

Resolving query type with promise in bucklescript

I've got this query im trying to test with with the reason graphql_ppx library. code gist
This is a screenshot of the editor type annotations:
Using the #mhallin/graphql_ppx library, i've got the following query set up:
module FilmQuery = [%graphql
{|
{
allFilms {
films {
id
title
releaseDate
}
}
}
|}
];
exception Graphql_error(string);
/* Construct a "packaged" query; FilmQuery takes no arguments: */
let filmQuery = FilmQuery.make();
/* Send this query string to the server */
let query = filmQuery##query // type string
I get an the following error when i send the query to the server it returns the following error.
{ errors: [ { message: 'Must provide query string.' } ] }
But if you Js.log(query) you see its being constructed which works on https://swapi.apis.guru
query films($first: Int) {
allFilms(first: $first) {
films {
id
title
releaseDate
}
}
}
If you Js.log(filmQuery) you get:
{ query: 'query {\nallFilms {\nfilms {\nid \ntitle \nreleaseDate \n}\n}\n}',
variables: null,
parse: [Function: parse] }
If your run the same query in Altair and you check the query that was sent in the devtools network tab you see:
{"query":" query films($first: Int) {\n allFilms(first: $first) {\n films {\n id\n title\n releaseDate\n }\n }\n }\n","variables":{}}
The editor is provided this type error:
"- error
[bucklescript]
This has type:
string
But somewhere wanted:
Js.t({.. query : string, variables : Js.Json.t })
string"
How do I get this promise/unit type resolved? Thank you.
So the new question is: Why isn't the sendQuery() function recognizing the filmQuery##parse key?
Your sendQuery method is expecting a type in the shape of what is returned from FilmQuery.make(), but you are passing it just the query property, which is a string.
You can fix this by passing filmQuery as into sendQuery instead of just the query property from filmQuery that is referenced by the query variable.

Resources