folkloreinc / laravel-graphql

Facebook GraphQL for Laravel 5. It supports Relay, eloquent models, validation and GraphiQL.
1.76k stars 234 forks source link

How GraphQL in Laravel actually work ? #271

Open gwynn-1 opened 6 years ago

gwynn-1 commented 6 years ago

I have researched basic GraphQL recently and as I read the explanation in https://dev-blog.apollodata.com/graphql-explained-5844742f195e, GraphQL execute nested query in tree structure, It means the top-level query resolver will be execute first, then the lower-level query resolver execute.

But when I test it in laravel graphql, I think it don't follow that rule. It just executes the top-level resolver with ORM query inside then return the values. Can someone explain me the workflow of laravel GraphQL ?? I'm very confused because what I know about GraphQL seem like it's not right in laravel graphQL library.

I hope someone will enlight me. Thank you

codeitlikemiley commented 6 years ago

there is only one level in making a request you pass in all the params its for you to decide what to resolve with those params if you building for example a nested relationship with user User

then you declare it all in your config all those types and query and mutation....

then just make an GraphQL api calls using graphqli endpoint for example

{
users{
name
email
post{
 title
body
}

}
}
gwynn-1 commented 6 years ago

Thank you for reply, but It's not what I mean. As I understand the GraphQL will execute the resolver from top-level node tree to the low-level node tree. For example, I have Books, BookType, Readers and Borrowdetail table. Borrowdetail contains all the info of borrowed book and the reader,BookType contains info of category of Book. So when I Query like this:

Borrowdetail{ id, readers{id,name}, books{ id,name, BookType{id,name} } }

I think it will run the resolver of Borrowdetail resolver first to get field from Borrowdetail. Then it will run the Reader and Book Query Resolver to get field from readers and books, and finally it will run BookType resolver. But when I test and implement graphQL in laravel, I think it don't work like the theory mentioned in https://dev-blog.apollodata.com/graphql-explained-5844742f195e .

I want to know how the GraphQL actually work, like how it executes the query, how it maximum the performance when there are so many nested query.

kikoseijo commented 6 years ago

The full picture as I see it, its that you make nodes and endpoints (queries) What this package achieves is the parsing of the query to your mutations or endpoints, parsing the input fields in the form of $args, with this you must build the SQL, its quite simple if you understand the concept.

What its important to take in consideration its the amount of queries needed to achieve the best performance results, but this is the mastering part. (maybe @supernhok13 its what you trying to understand)

This package, as I been exploring, please correct me if im wrong, gives you the 2 first bits of the GraphQL server implementation on a query resolution aspect, which is to parse the query and validate input fields, after this is your turn to provide the records in the format your query is expecting, another good thing you also get its to clear out the fields you don't need to give back, you can return full record in your function, this package clears whats not needed and your client only receives what it asked for.

Another cool feature its that by modelling the Types, Nodes and so, you can make and endpoint where you schema its declared, for example: using the admin schema:

$router->get('/schema.json', function () use ($router) {
    $schema = GraphQL::introspection('admin');
    return response()->json($schema);
});

Having this you can have a model schema definition, something similar to what swagger provides, there are tools for React where you can synchronise your client app with your server with packages like graphql get-schema or relay-compiler, this makes your development a complete different experience, his is so cool for the fact that you are pre-compiling and validating all network calls, and define for your the types in your client app. Its always good to have some checks where your code its matching the server specs.

correct me if im wrong, or is there more into this I still don't see.

codeitlikemiley commented 6 years ago

query nested relationship will always go down to the database level... if you make N+1 Querry surely you does not optiize your 1 endpoint of quering all data in one go... EagerLoading Relationship is the best way to go....

Maybe you can listen to the number of querries your making in one go... Ive been reading a lot lately, researching just like you do...

but hopefully this helps you

gwynn-1 commented 6 years ago

Ok Maybe I understand a little bit. Thank you guys for sharing me your knowledge. Let me say it again for more clearer, if I'm wrong at some part, please correct me. So the explanation in the link I mentioned is when it executes in database level, and in this library of Laravel, it's how the ORM Eloquent work in Resolver function when client request for nested GraphQL query.

My boss want me to research about GraphQL's performance so that we can know it is qualified for our upcoming microservices project, especially in Laravel and Lumen. So I hope you guys can help me out :))

ikudosi commented 6 years ago

I've been using GraphQL with this package on two different companies. Because GraphQL is a spec, the performance is all up to you on how you construct your data. The way it works is in the resolve method of the query, you return an entity that represents the type you defined in that query. GraphQL will take each field that you pass to the back, and access them as a property so it is best to utilize relationships as much as possible and to eager load your relationships when needed. The way I have it setup right now is I created my own base ModelQuery class that all queries extends from. What that class offers standardized global parameters like relationships / limit / order / searching columns; relationships is an array of string where you pass it literally the relationships to load in the back. I'm pretty sure you can create such logic to eager load everything automatically based on the fields you pass to the back but I haven't gotten the time to think of that whole process yet.