9 ms·
Can someone please explain what GraphQL actually is? I've looked at it multiple times but never got super deep... my limited understanding is that all it is is
by Exuma 7y ago
Can someone please explain what GraphQL actually is? I've looked at it multiple times but never got super deep... my limited understanding is that all it is is basically defining a schema so that when issuing API requests, the client itself can make it's own "query request", rather than talking to an app backend which has SQL queries programmed/written in an ORM or some database wrapper.
I feel like I'm missing something, as that seems incredibly limited, especially with things like performance (where queries need to be tuned and refined and custom written. Just a simple SELECT * FROM X INNER JOIN Y and horrible N+1 isn't good enough)
Can someone please explain what is GraphQL once and for all?
- Doxin 7y agoGraphQL seems to be mostly touted as "You can do richer queries!". which is definitely true, but not the key factor of what makes it awesome in my experience. Much more important to me is how it allows the backend and frontend to work closer together. I can simply send the frontend developers my schema and then they know exactly what each endpoint returns, down to the exact type of the returned keys. There's no more back and forth on what the data for a new endpoint is supposed to look like. Either the backend devs take lead and hand a schema to the frontend devs, or the frontend devs take the lead and hand a schema to the backend devs. Other than that there's quite a lot of really cool tooling. On the backend (python/django) I'm no longer needing to write long-winded serializers for each specific kind of view. I can simply make a query object that returns the right database query. On the frontend (typescript/react) they no longer need to write types for each API view, they can simply hand the schema to a code generator and get a file out declaring all the types the API deals with. GraphiQL is awesome for both frontend and backend devs, At the very least it's a tidy small editor for queries. It allows you to run queries as you're developing or testing views. The documentation pane shows all the return types and expected arguments and types even if you don't put any effort into documenting anything. If you do put effort into documenting it becomes a powerful API documentation that's be easy to keep up-to date. We're still in the early days of using graphQL but what I've seen so far certainly is worth the growing pains we're going through. The only real nitpick I have is the poor documentation of graphene-python, quite a lot of crucial use cases have you running around stack overflow and the source code to find answers. The case that gave us the most trouble so far (backend and frontend) is what to do with errors. We've gone the route of having views returning a union of the result and a global error type, which seems to be working nicely so far. Of course the richer queries are nice too, but for us they seem to be mostly limited to making queries return less info when possible. e.g. when querying users you don't always need to return the entire user, which graphQL supports nicely, allowing you to elude profile photos or other expensive-to-calculate-columns whenever needed.
- hakanito 7y agoBasically GraphQL is an API contract between a client and a server. The contract defines what data, through types and fields, is available. The server must fulfil this contract by providing methods (called resolvers) for each field. The client must fulfil this contract by only asking for available fields. The query language is built to support highly nested data. Now, the N+1 problem you are talking about is not a GraphQL problem, but an implementation problem. Depending on how you write your server methods you can get it down to very few db calls (some use a thing called dataloader. Other tools are hasura or postgraphile)
- cheez 7y agoBuild the data request you want at the client rather than the server
- soulnothing 7y agoI went to a talk where it labeled it as halfway between a dsl and sql. I haven't used it in about a year. ``` user { id, first_name } ``` would on the back end map to a function that runs something like. ``` select id, first_name from users ``` So the fields are dynamic in a way. Allowing you to select only the data you want. You can also nest data calls, like joins. ``` user { id, first_name, user_profile { bio, recent_comments } } ``` This would execute the above. Then take that user object into a query context. That query context allows you grab any elements from the parent returned object. I.E. the user id. That would then execute the nested query like ``` select bio, recent_comments from user_profile where id = $user.id ``` So instead of rest end points. You are building a number of functions that return an object. You can then define relations that operate off of those returned objects. You can also restrict queries in production. So only white listed / approved queries are run. A schema is a list of all these objects that may be returned and their relation also including type. Instead of a reverse proxy like nginx. There is schema stitching. Which combines all the schemas into one big schema. When querying it will proxy the respective calls to the respective back end services. I did a talk on GraphQL a bit ago, so it may be out dated. https://blog.animus.design/kotlin-backend-presentation/ https://blog.animus.design/kotlin-backend-presentation/ Corresponding repo https://gitlab.com/AnimusDesign/KotlinIMDBDemo/blob/master/api/src/main/java/design/animus/kotlingraphqlrestpresentation/api/graphql/service/NameBasicService.java https://gitlab.com/AnimusDesign/KotlinIMDBDemo/blob/master/a... I've not used Graphql in production. When I was researching it's ecosystem anything outside of JS leaved a bit to be desired. That being said. It's a solution to a problem. Openapi can generate clients. But if you need to make six calls. It's not performance or transit time. It's cleaning up the errors on that. Waiting for one to respond then another. From that vantage point I see the benefit. One query get what you need. If anything fails along the way it stops. It shifts the error checking pattern to the server. Additionally in react and even mobile. There are redux or state machine stores that operate strictly off of graph ql. You've now centralized data retrieval, and state management of the app. That's a pretty big win. https://www.apollographql.com/docs/react/data/local-state/ https://www.apollographql.com/docs/react/data/local-state/ All of this is very beneficial to the front end / mobile. Easing data retrieval, being more expressive and type safe. But it's the front end driving how data is presented and stored to an extent. By using graphql to get the best support you should be running on node.
- ricw 7y agoGraphQL allows you to not only fetch a single piece of data, but allows you to also fetch related data, ie traverse the relational graph of data. So if you have friends, and sometimes want to fetch your friend's latest posts/pictures, you can do so as you like with one single query. In REST, you would first get all your friends, then for each of these friends get all the posts/pictures as individual queries. In short: it allows you to query a database much more naturally in one go, rather than having to fetch data, and depending on that data then fetch more data. On top of that, it's typed, relatively easy to learn and well documented. I'd highly recommend it, even if it's a tad more complicated than plain REST.
- Exuma 7y agoI guess I already do this with "REST" (although I get it's not really called that much if I don't strictly follow 1 resource per request). But I very often just make endpoints that have custom SQL written that touches many tables anyway.
- pluma 7y agoThat seems to be how most people do it in the wild if they don't have any reason to try to stick with a pure REST/HATEOAS API. Frequently when people say they do "REST" that can mean as little as "we use different HTTP verbs for the same endpoint to distinguish between calls rather than putting those verbs in URLs" (e.g. POST to a collection rather than to a route "/new", DELETE to a resource rather than POST to a route "/delete"). GraphQL was developed at Facebook and Facebook has a massive backend API used by many different teams for many different purposes. In this scenario the trade-offs were apparently worth it because purpose-built endpoints for each feature were likely not scalable and would have required deep knowledge of the full stack to implement. In teams of 1-10 people with an API that serves a single app controlled by the same team, I'm not convinced GraphQL adds much apart from adding a layer of complexity to the architecture.
- Exuma 7y agoMakes total sense, Thank you
- deleted 7y ago[deleted]
- ClumsyPilot 7y agoIt's like a dumbed-down version of SQL for clients to query the server. It's not totally arbitrary, it kind of let's you tie together micro-requests. You backebd might be using an ORM. It might be pulling data from 10 different places and exposing them in a single api. Optimisation can be an issue.
- deleted 7y ago[deleted]
- nlh 7y agoYes - (and totally reasonable question, btw - it's remarkable how hard it is for the folks behind it to just plainly state what it is vs. coating it in buzzwords). BTW - I may be wrong / misunderstanding something here as I'm only in the research phase, but here's what I got: GraphQL is an alternative to REST as a way for clients to query servers for information. In a REST query, you hit an endpoint and add optional query params. But you get back results based purely on what the server has been singularly designed to give back. For example, if I query: GET /users/1 I'll get back a user object that the server has been programmed to return. It's of course possible to customize this with query params, and do something like: GET /users/1?only_include=first_name,last_name But that's the exception to most RESTful APIs, not the norm. In a GraphQL query, the client specifies _exactly_ which fields it wants back, and that's baked into the design. So the client would submit a query like this: { user(id: "1") { first_name last_name } } And the server would return exactly the object the client asked for. There's no magic here -- that's the part that many people have trouble explaining. When you write your GraphQL server, you still need to write the actual queries (<--- this is the key!). But structurally, you write more generic queries -- you'd say "when a client requests a user, run this SQL", "when a client requests first_name on a user, run this SQL", etc. etc. That way on the server, you write isolated query resolvers (called, amazingly enough, resolvers), each of which get run when a query comes in. This is as opposed to a RESTful approach, where you'd do a more traditional single SQL query for the /users/:id endpoint (SELECT * FROM USERS WHERE ID = ... ) Hope that makes sense (and is accurate!)
- AndrewOMartin 7y agoYour understanding matches my understanding, but you missed the point which was the "ah ha!" moment for me. Which is that the front end developer can design their own endpoints without bothering the back end developer. When a front end developer wants to request a specific shape of data (e.g. All the people with age between x and y who are within a distance of z of the logged in user and just get their name and list of interests) then with REST they have to either compose that data from the available endpoints or bother a back end developer for a new endpoint. With GraphQL the front end developer can compose the query themselves without knowledge of any back end technology beyond the GraphQL schema. E.g. they'd write something like the following, using either a schema reference, or introspection-powered autocomplete UI to find out which fields are valid. query nearbyCandidates { allUsers(filters{ isTheLoggedInUser:false, ageBetween:{start:x, end:y}, closerThan:{distance: z, from: [LoggedInUserPosition]}, }){ interests:{ interestName:name, description, } candidateName:name, } } This actual story is a bit of a fairy tale because you'd still need the two developers to interact if the required fields or filters did not exist. Finally the general theme of the comments here, that there's nothing stopping you using both, is accurate.