GraphQL Alternative: GraphQL vs. AskQL
source link: https://yonatankra.com/on-covid-19-graphql-and-askql/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
How does AskQL differ from GraphQL?
Efi Shtain’s question was repeated in various forumsAfter writing about AskQL and how to use AskQL with nodejs, the obvious question that repeat itself was: How does it differ from GraphQL?
In this article I will try to show the main benefits of AskQL by converting a simple Covid-19 GraphQL project into AskQL.
The Project
The project is a small Covid-19 api server powered by GraphQL. Here’s the original repository:
https://github.com/vinitshahdeo/covid19api by Vinit Shahdeo
This repository sends some queries to an open covid-19 api and returns them to the client.
I’ve forked the repository and added a simple client to it. Let’s look at its code.
The GraphQL Server
Code snippet #1 shows the GraphQL server setup. It sets up the client (line 7). It then sets up a GraphQL endpoint via the GraphQL express middleware (line 9).
By going to http://localhost:8081, you can actually get to the UI that is connected to the GraphQL server (Figure 1).
Figure 1: the GraphQL query UI. Just enter a valid query and get the results back.The actual GraphQL magic happens in the schema.js
file (Code snippet #2).
Lines 12-67 in Code snippet #2 are the definition of 3 GraphQL object types (CovidDataType
, StateCovidDataType
and DailyCovidDataType
).
Lines 72-100 in Code snippet #2 define another object type that also includes resolvers for 3 properties: total
, statewise
and datewise
. Each property is of the Object types defined above respectively.
The resolvers for each property fetch data from the covid api, and return a certain portion of it.
Lines 102-104 just export a GraphQL schema that is passed to the GraphQL express middleware.
If you try to enter the following queries, you will get the wanted results:
GET
overall COVID-19 stats
{ total { active confirmed deaths recovered } }
GET
statewise COVID-19 stats
{ statewise { state active confirmed deaths recovered } }
GET
datewise COVID-19 stats
{ datewise { date dailyconfirmed dailydeceased dailyrecovered } }
The AskQL Server
For this purpose, I’ve just used the AskQL server from the AskQL Nodejs Quickstart article. By cloning it and using the main branch, you will receive the exact same query UI – only this time the backend is powered by AskQL.
Now – part of the power of AskQL is that we don’t really need to do anything to make the same queries work. For instance, if we’d like to get the datewise
data set, our AskQL query will look like this:
ask {
fetch('https://api.covid19india.org/data.json')['cases_time_series']
:map(fun(dataSet) {
return {
data: dataSet['date'],
dailyconfirmed: dataSet['dailyconfirmed'],
dailydeceased: dataSet['dailydeceased'],
dailyrecovered: dataSet['dailyrecovered']
}
})
}
Code snippet #3: An AskScript that can be pasted into the AskQL demo website.
Code snippet #3 is written all client side, but the same as the GraphQL datewise
query.
The difference here – we did not need to make any change serverside.
AskQL Resolvers
As shown in Code snippet #2, you can create resolvers in GraphQL. For parity sake, I’m going to show how AskQL resolvers work.
In AskQL, the resolvers are called resources
. Let’s create the statewise
resource in AskQL.
statewise.js
) and the AskQL express middleware setup with the custom resource (askql.js
).In Code snippet #4, in the statewise
file (bottom) we have a simple code that does the same as the GraphQL statewise
resolver.
Line 8 fetches the data, line 9 returns the JSON, line 10 returns the part of the data we want (all except the first array member) and line 11 does the mapping into the schema we want.
In the askql.js
file (top) you can see the custom resource is added to the list of resources sent to the AskQL Express Middleware
in line 9.
The query that calls for the statewise
resource is shown in Code Snippet #5.
ask {
{
data: {
statewise: statewise()
}
}
}
Code Snippet #5: The statewise query in AskQL.
This returns exactly the same data as the GET
statewise COVID-19 stats GraphQL query mentioned above. You can see the two queries side by side in Figure 2.
The Big Deal
We saw above that while we can create resolvers in AskQL, they are not always needed.
While in GraphQL you’d need to create resolvers for new types of data, in AskQL you are not limited to what the backend team created for you as a client.
Why is this so valuable?
There are many use cases for this.
No need to deploy a new server version
There might come a time when the client needs some new data from the existing dataset. For instance – statewise
also includes the lastupdatedtime
property.
The GraphQL server does not expose this to the client. In order to expose this to the client, the GraphQL server needs to be redeployed with an updated schema.
Not so for AskQL. As we saw in Code snippet #3, you can send the mapping instruction via the AskScript query, directly from the client.
This means, the client team can move ahead without waiting for a server redeployment.
Access to new resources
The last use case was accessing data that was hidden by the resource/resolver.
Another use case is a situation in which the remote API was upgraded, or a new microservice was raised with information you need in order to farther enrich your data.
In the GraphQL server, this would again require the backend team to redeploy a new version of the server.
In AskQL, it is as easy as writing a new script.
In our example, the JSON fetched was showing data by states in India. A new microservice was created that handles the data by districts (https://api.covid19india.org/state_district_wise.json).
Instead of creating a new resolver in the backend, the client side can just do the following:
ask {
const statewiseData = statewise();
const districtData = fetch('https://api.covid19india.org/state_district_wise.json');
statewiseData:map(fun(stateData) {
{
stateData,
districtsData: districtData[stateData['state']]
}
});
}
Code Snippet #6: The statewise query enriched with district data in AskQL.
In Code snippet #6 we get the states data array, and enrich it with the district data fetched from the new server. As easy as that.
You can check the covid-19 branch in the askql-demo repository for the full example.
Why no just query from the client?
That’s a good question, and there are various reasons for that. One reason that comes into mind – especially in commercial applications – is security.
The AskQL server will be an internet facing server. It might be that it has access to non-internet facing servers inside an AWS VPC (or other cloud vendors equivalents).
So the AskQL server is mainly a security gateway for the client to be able to fetch data that is not internet facing and thus is not available directly.
Performance-wise, servers might have an optimised access to some resources. The fetch request might actually be much faster via the AskQL proxy rather than directly from the client.
Another performance use case can be caching – the AskQL server might handle requests caching and serve them in order to reduce the load on more expansive resources like DB’s.
Summary
In the past, the DB was the “King” and the clients had to code accordingly. DB normalisation came into effect in the client’s code.
GraphQL came to solve the “DB is king” problem. It’s now possible to allow the frontends to query as they know – simple JSONs that fit them.
In this article we saw that AskQL solves this issue, just like GraphQL does, but goes one step farther.
AskQL allows more flexibility since the client is not dependent on schemas set in the server. This way, it allows the client(s) to advance without waiting for the server to redeploy.
This reduces the coupling between client and server.
Besides flexibility in a single client, this allows us to build multiple clients that have different needs with only one (scalable) endpoint.
The fact that one endpoint can serve multiple clients, and indeed, multiple types of clients, we can use optimisation techniques like caching in order to improve performance and save valuable money for our growing company.
You can try out AskQL in the official repository, and also meet the AskQL team over at the AskQL discord channel.
Thanks a lot for Omer Koren from webiks and Piotr from xFAANG for the kind and thorough review!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK