Query only if non-boolean argument exists - graphql

I'm trying to find a way to achieve include multiple queries in the same query based on required arguments.
This might be confusing, so let's take a look at an example
If we have 2 resolvers both with required IDs, let's say:
post(id: ID!) {...}
user(id: ID!) {...}
And we want to fetch both within the same query/request, but we might or not have an ID like the user, something as:
query($postId: ID!, $userId: ID) {
post(id: $postId) { ... }
user(id: $userId) { ... }
}
Now if we look we see that $user: ID is not mandatory in the query, but it is in the resolver.
I've looked at #include and #skip directives although, I didn't find a way to convert the $userId to a boolean.
Also, I've tried to pass a boolean as shouldIncludeUser although, as expected, the GQL will complain that the variable $userId of type ID doesn't match the type ID!.
Any ideas ?
Is this even possible?

Related

Why do you need to wrap GraphQL mutations?

I have never understood why GraphQL mutations need to be "wrapped". You'll often see something like this demonstrated (assuming a mutation named addThing which requires a name):
mutation addThing($name: String!) {
addThing(name: $name) {
id
name
}
}
However, the outer "wrapper" could be named anything. For example, the following nonsense works equally well:
mutation nonsense($name: String!) {
addThing(name: $name) {
id
name
}
}
What is the reasoning for "wrapping" the mutations this way?

How to filter a Graphql query with a field value in Laravel 5.8 with Lighthouse

I have users who can create lists. Lists can be starred ("featured" if you prefer). I want to build a Graphql query in Lighthouse/Laravel that would retrieve all the starred/featured lists for a given user.
I tried this query and it works:
clistsByStarred(user_id: Int! #eq, starred: Boolean! #eq): [Clist] #all
and then I can use it like that:
query {
clistsByStarred(user_id: 1, starred: true) {
id
name
starred
}
}
But it feels like a dirty hack to me.
What I would like to achieve is this:
query {
user(id: 1) {
id
name
clistsByStarred {
id
name
starred
}
}
}
Any idea on how to implement it ?
type User {
id: ID!
clists(starred: Boolean #eq): Clist #hasMany
This example gives you a user type which has a list of Clist types.
You then just add a field in your query to get a single user by id.
When you query this, you can then specify the parameter starred to only get the starred.
For this to work the relationship has to exist on your eloquent model.
https://lighthouse-php.com/master/eloquent/relationships.html

How to use the query for custom fields on GraphQL?

I have this schema on my graphcool:
type User #model {
id: ID! #isUnique
name: String!
email: String!
password: String!
}
Using playground, I can execute this properly:
query {
User(id: "1234") {
id
name
}
}
But this query:
query {
User(name: "Thomas") {
id
name
}
}
throws error:
Unknown argument 'name' on field 'User' of type 'Query'. (line 2,
column 8):
User(name: "Thomas").
Why? And how to fix this? From my pov, anything that's already on the model, can be queried immediately, right? Btw, I'm very newbie in graphQL, and there's almost no article talk about this error (every tutorial just like assume that this will immediately works), so please give some more elaborate answer if necessary.
GraphQL does not intrinsically allow arbitrary queries against objects.
Somewhere in your schema there will be an additional declaration like
type Query {
User(id: ID!): User
}
The names in the Query type are the top-level queries you can run, and the arguments listed in that query are the only arguments they accept. (There is a corresponding Mutation type for top-level mutations, which can change the underlying state, and use the mutation keyword in a query.)
If you control the server implementation, you could add a parameter or an additional top-level query
userByName(name: String!): User
but you'd also have to provide an implementation of this query or handle the additional parameter, which is a code change.

Apollo / GraphQL Same Query with Different Parameters

How would I go about having an Apollo query with different parameters. Let's say my app has the concept of users and I want my API to be able to find a user either by ID or username.
It doesn't seem I can do this
type Query {
user(id: ID!): User
user(username: String!): User
}
do I have to resort to something like this
type Query {
userById(id: ID!): User
userByUsername(username: String!): User
}
Create a new input type with ID and username as fields and specify it as parameter.
type Query {
getUser(filters:UserFilter): User
}
input UserFilter{
ID : Int,
Username : String
}
Query should look like this ...
Query{
getUser(filters:{ID:123123})
}
OR for username filter
Query{
getUser(filters:{Username:"Tom"})
}
I believe your second option is the best however you could do something like this.
type Query {
user(id: ID, username: String): User
}
If the parameters are not required then your resolver could use some logic to determine if it should get the user based on the id or the username.
if (args.id) {
return getUserById(args.id)
} else {
return getUserByUsername(args.username)
}
However for reasons gone over in this talk https://youtu.be/pJamhW2xPYw?t=750 (maybe see at about 12:30), I believe your second option is a better design choice. Hope that helps!

How to search string values in GraphQL

How do you query using GraphQL in a manor similar to SQL's like operator?
Example: What users have a first name starting with jason?
select * from users where first_name like "jason%"
The short answer is: you don't.
The longer answer is that you have to write that code yourself. GraphQL isn't a database query language like SQL, it's an application query language. What that means is that GraphQL won't let you write arbitrary queries out of the box. It will only support the types of queries defined in your GraphQL schema.
If you want to be able to write a query that contains like, you have to
a) declare that in the schema, and
b) write a resolve function that fetches the data
For example, you could have this schema:
type Query {
users(firstName: String!): [User]
}
type User {
firstName: String
lastName: String
}
You would have to define the following resolve function for the users field:
{
Query: {
users(root, args){
return sql.raw('SELECT * FROM `users` WHERE `firstName` LIKE ?', args.firstName);
}
}
}
And finally write this query to get a list of firstName and lastName of all the users that match your search criteria:
{
users(firstName: 'jason%'){
firstName
lastName
}
}
Here's a post I wrote a while ago that clarifies some of the concepts around GraphQL: https://medium.com/apollo-stack/how-do-i-graphql-2fcabfc94a01
And here's a post that explains the interplay between GraphQL schemas and resolve functions: https://medium.com/apollo-stack/graphql-explained-5844742f195e
Not sure if this is relevant to you because you want it to start with "jason" (ie would return "jason bourne" but not "bourne jason") but I recently came across a way to query GraphQL in a "%Like%" manner. For your use case it would look something like this:
export const allUsersQuery = `
query allUsers($UserName: String!){
allUsers(
filter: {first_name_contains: $UserName}
) {
id
first_name
...INSERT_OTHER_FIELDS_HERE...
}
}
`;
FWIW: I did this using a GraphCool BAAS. I don't think you were using GraphCool because GraphCool doesn't allow "_" in variable names.
Hope this helps someone down the line :)

Resources