In an attempt to help resolve this issue, I suggest that you think of it as ProductQL or ProductAPI instead.
It's not a storage layer. It's not really a query language. It's an alternative way to define an API that more closely matches the typical mental and product domains than REST.
It's critical to realize that you're implementing an API. GraphQL does not concern itself with sorting or fetching data as the name might lead you to initially believe. It has little to actually do with graphs (except they are more easily expressed). It is designed to be added on top of your application layer and business logic to provide a single, well defined API for your product and tools.
It primarily targets product developers. From the scheme/API side, it is up to the server developer to decide what to expose and how, based on the product and any technical considerations that need to be made.
Compared to SQL, this is done using an unusual manner, giving a shape of the data we want around some seed, but the approach is both expressive and efficient. In light of this query principle, it is perhaps unfortunate that GraphQL use a different syntax for the query and the response. To this regard, freebase's MQL is more pure (http://wiki.freebase.com/wiki/MQL).
About graph, I think the term applies too. Indeed, a GraphQL defines a subgraph to be extracted from a whole graph, even if the tree shape of the response forces to resort to ids to tie the loop.
Compared to a graph traversal query language like Gremlin (https://en.wikipedia.org/wiki/Gremlin_%28programming_languag...), I find the pattern approach of GraphQL simpler to grasp; and even easier to implement efficiently in a distributed setting. I implemented years ago a distributed graph database for Yahoo!; and the query language, based on shapes to be extracted around seeds, was a key design choice for an efficient architecture and short query delays.
In an attempt to help resolve this issue, I suggest that you think of it as ProductQL or ProductAPI instead.
It's not a storage layer. It's not really a query language. It's an alternative way to define an API that more closely matches the typical mental and product domains than REST.
That is a tremendous and useful insight.You start with a root query object and then call a bunch of methods on it of the client's choice and put the results in a dictionary.
Then you do that recursively on the resulting objects until you have data consisting of nested dictionaries and lists containing only primitives, which is finally serialized as JSON and returned.
1) Give me data in the right shape for my problem please server.
2) Server responds with data in a shape that matches what it was asked for.
3) Update the store of your frontend and trigger any updates to UI (react does this automatically).
Save countless hours of writing fine grained rest APIs to support various different ways of requesting data or munging data into the right format on the client.
And by the way we've made it super easy to bundle requests together in a nice way saving trips to the server.
For sure. If I could still edit the post, I would probably change it to be something closer to "it's not really a general purpose query language like the name might imply"
It's definitely a query language, but folks start looking for the sorting/filtering/etc and get confused.
In other words, what stops anyone from easily disabling a website by making a few parallel extremely complex GraphQL requests that consume all CPU and I/O, and perhaps result in holding some locks for a very long time?
In normal APIs you can make sure most endpoints are cheap to run, and throttle, secure or otherwise control the ones that must be expensive, but that doesn't work if you expose a flexible layer like GraphQL (or SQL).
user {friends {friends {friends {friends{id}} } } }
case (which is the canonical example in FB's schema of a crazy query), we would note that there's a 5000 friend limit, and so that query would potentially query 5000^4 = 6.25e14 nodes, and based on that we would (hopefully) reject it.For example, a query like "user {moviesWatchedByUser {usersWhoWatchedMovie {moviesWatchedByUser {usersWhoWatchedMovie ..." is allowed by GraphQL and will generate output with size exponential in the input size.
You can also do "{a1: expensiveOperation, a2: expensiveOperation, a3: expensiveOperation, ..." and trigger expensiveOperation an arbitrary number of times (for each item in the list you apply that to).
By using a sequence of fragments that include the next fragment more than once, it looks like you can trigger expensiveOperation an exponential number of times.
It's not clear if there is a way to prevent all this without severely impacting usabilty (by warping the schema design and adding GraphQL limits to handle this) or reliability (by enforcing hardcoded low resource usage limits).
But at the end of the day, most data can be considered graph data. It doesn't have to be represented as a formal graph.
To take the Star Wars example at https://github.com/facebook/graphql and build on it. Let's say after this is deployed we need to expose a Planet's population as well. Now homePlanet goes from being a String to a Planet { name population } object.
This type change would break existing clients - the only real solution I can think of is introducing the planet object as PlanetDetails (essentially PlanetV2) and deprecating planet, but that's just back to versioning.
I feel like there must be a better way to deal with it? Interestingly, the graphql format allows this to be differentiated (as the old API won't request an object), but there appears to be no provision to union two non-objects into a single field?
Whereas contrasting with REST versioning or traditional versioning, it becomes quite difficult to mix API versions internally (each callsite needs to specify their desired api version before specifying fields) or impossible outright. If the latter, you're then forced to migrate all at once from a given version to another, which requires a ton of coordination across teams and big scary "flip the switch" moments.
This gets worse as you scale up your org, which is why GraphQL has served FB well.
It's totally unclear to me that GraphQL solves data migration problems.
Ultimately syntax is useful to express domain-specific concepts in a terse way.
I'm not too familiar how this works, but maybe it's enough to query the additional data in parent component or somewhere and it just works.
What about complex predicates (and, or)?
The language seems rather limited.
For example, we might have the following query on Facebook's GraphQL schema:
{
user(id: 4) {
followers(isViewerFriend: true, birthdaysInRange: {before: -2, after: 2} orderBy:NAME) {
name
}
}
}
EDIT: fix code formattingWhich fetches Zuck's followers, and filters it to only my friends, and only those friends whose birthdays are within two days of today, and then orders them by name.
The `isViewerFriend`, `birthdaysInRange` and `orderBy` parameters were explicitly added to the API by the API developer for clients to use.
So clients don't have the ability to do arbitrary operators, but we also know that the client is only using functionality in the API that the API developer chose explicitly to allow.
Ok. I was hoping things had gotten better.
https://github.com/facebook/relay/blob/master/src/network-la...
It's true that we've passed peak colon as a culture, and need to start reimagining life in a post-colonial way, but...
We've got a reference lexer and parser in JS at https://github.com/graphql/graphql-js/tree/master/src/langua..., and we have a parser in C++ with C and C++ APIs (that can be used to build a parser for other languages) at https://github.com/graphql/libgraphqlparser.
...but we had some really ugly JSON. It was worth it for us to get the readable syntax to just use GraphQL.
With client tooling like GraphiQL and editor plugins, it should just get better.
https://github.com/lukemurray/EntityQueryLanguage
Super early days as I haven't had too much time on it, and now GraphQL has specs etc. I might support more of it's syntax.
I actually build .NET expression so you can execute things against any LINQ provider - in-memory, Entity Framework, or some other ORM
http://www.odata.org/getting-started/understand-odata-in-6-s...
The GraphQL server can pass down authentication information through the query using `rootValue` (for example, it might pass the OAuth access token that the client provided in the request), which the mapping from GraphQL-to-application-code can pass to the application code's access controls.
Implementing API-specific functions in the query? That looks an awful lot like adhoc RPC endpoints, because the functionality is application-specific.
I just don't get the hype. Poor documentation, no robust reference implementation... nothing novel about the query language itself. Function calls in queries is pretty much just RPC (even if you say "declarative" a lot). And if it's about graph data it's incredibly limited compared to SPARQL.
The proliferation of ad-hoc REST endpoints is a serious problem. Standards like JSON API (http://jsonapi.org/) do a good job of mitigating the issue (and are probably a good first step for preparing your API for being encapsulated within a GraphQL server), but they are just a band-aid around the problem.
We've all concluded that mobile apps (for now) should only be making one API request to get all data needed (if possible), so we end up constructing custom end-points per use-case that return exactly what's needed. Then a new version of the app comes along with slightly different data requirements, so we make a new end-point. We end up in a really bad place. Developer discipline is part of the problem, but the fact is that we're probably using the wrong technology.
SOAP was awful, REST is much nicer. But GraphQL is a dream. It genuinely feels like every time I add a new piece of data to my schema, my productivity accelerates. A well-considered, well-maintained GraphQL server is a significant improvement over REST endpoint. GraphQL may not be the ultimate solution here, but it solves a lot of pain-points i've been having for the last few years.