Interested in speaking at MongoDB World 2022? Click here to become a speaker.
HomeLearnArticleA Free GraphQL API for Johns Hopkins University COVID-19 Dataset

A Free GraphQL API for Johns Hopkins University COVID-19 Dataset

Updated: Dec 10, 2020 |

Published: Sep 25, 2020

  • Atlas
  • Realm
  • API
  • ...

By Maxime Beugnet

Rate this article

#TL;DR

You can retrieve an access token using the API like so:

1curl -X POST 'https://realm.mongodb.com/api/client/v2.0/app/covid-19-qppza/auth/providers/anon-user/login'

Then you can read the GraphQL API documentation and start running queries like this one using the access token you just retrieved:

1curl 'https://realm.mongodb.com/api/client/v2.0/app/covid-19-qppza/graphql' \
2 --header 'Authorization: Bearer ACCESS_TOKEN' \
3 --header 'Content-Type: application/json' \
4 --data-raw '{"query":"query {countries_summary {_id combined_names confirmed country country_codes country_iso2s country_iso3s date deaths population recovered states uids}}"}'

#Introduction

Recently, we built the MongoDB COVID-19 Open Data project using the dataset from Johns Hopkins University (JHU).

It's a great dataset for education purposes and for pet projects. The MongoDB Atlas cluster is freely accessible using the user readonly and the password readonly using the connection string:

1mongodb+srv://readonly:readonly@covid-19.hip2i.mongodb.net/covid19

This cluster contains 2 databases: covid19 and covid19jhu. Only the first one will be exposed with this GraphQL API. The second one contains the unprocessed raw data from JHU's CSV files. Learn about the databases and collection in the dedicated blog post.

You can use this cluster to build your application, but I also set up a GraphQL API using MongoDB Realm to expose this data for you.

In this blog post, I will first show you how to access our GraphQL endpoint securely. Then we will have a look at the documentation together to build out a variety of GraphQL queries to access all sorts of information in our dataset - all against a single API endpoint. Learning how to to use filters and request only specific fields in our data will help optimize the performance of your applications - by bringing you exactly the data you want - nothing more, nothing less.

Trevor Noah saying wow gif

#Prerequisites

  • Command line and cURL - which I'm using here for the sake of simplicity.
  • Or any other tool which handles HTTP queries. I also tested to run the following queries with Postman, and it works great.

#COVID-19 GraphQL API

#Get an Access Token

I used MongoDB Realm to create this GraphQL API. Since MongoDB Realm is secure by default, only authenticated queries can be made. Yet since I want to keep this service as open as possible, I simply used the Anonymous Authentication offered by MongoDB Realm.

So now, all you need to retrieve an access token is the MongoDB Realm Application ID — or APP_ID, for short — of my MongoDB Realm application:

1covid-19-qppza

And the API to authenticate HTTP client request, which is:

1curl -X POST 'https://realm.mongodb.com/api/client/v2.0/app/<APP_ID>/auth/providers/anon-user/login'

Inserting the APP_ID into the URL gives you:

1curl -X POST 'https://realm.mongodb.com/api/client/v2.0/app/covid-19-qppza/auth/providers/anon-user/login'

If you execute this query in your favorite shell, you will receive a JSON answer that looks like this one:

1{
2 "access_token":"eyJhbG......6dbnY",
3 "refresh_token":"eyJhbG......uKpoM",
4 "user_id":"5f692c44033b9e7f1554d475",
5 "device_id":"000000000000000000000000"
6}

Access tokens expire 30 minutes after MongoDB Realm grants them. When an access token expires, you can request a new one using the same API, or you can get a new one using the refresh token. Although it's often just easier to request a new one.

#Query the GraphQL API

Once you have the token, you can start browsing the GraphQL API documentation that I generated with GraphDoc and build your first query.

Five collections are available in this GraphQL API, and you can learn more about each one of them in our documentation. Each have a "singular" query which can be used to retrieve a single document and a "plural" one to retrieve a list of documents. As an exception, the metadata collection contains only a single document so it offers no "plural" query.

You can see all the possible queries in the "query" page in the documentation, but I have also summarized them in the following table:

GraphQL API
CollectionQuery (singular / plural)Fields available
metadata
  • metadatum
  • _id
  • countries
  • states
  • states_us
  • counties
  • iso3s
  • uids
  • first_date
  • last_date
countries_summary
  • countries_summary
  • countries_summarys
  • _id
  • combined_names
  • confirmed
  • country
  • country_codes
  • country_iso2s
  • country_iso3s
  • date
  • deaths
  • population
  • recovered
  • states
  • uids
global
  • global
  • globals
  • _id
  • combined_name
  • confirmed
  • country
  • country_code
  • country_iso2
  • country_iso3
  • date
  • deaths
  • loc { type coordinates }
  • population
  • recovered
  • state
  • uid
global_and_us
  • global_and_u
  • global_and_us
  • _id
  • combined_name
  • confirmed
  • country
  • country_code
  • country_iso2
  • country_iso3
  • county
  • date
  • deaths
  • fips
  • loc { type coordinates }
  • population
  • recovered
  • uid
us_only
  • us_only
  • us_onlys
  • _id
  • combined_name
  • confirmed
  • country
  • country_code
  • country_iso2
  • country_iso3
  • county
  • date
  • deaths
  • fips
  • loc { type coordinates }
  • population
  • state
  • uid

Find all the details in the GraphQL documentation. To explore this data and the flexibility of GraphQL, let's build out three example queries.

#Query 1. The Metadata Collection

Let's first query the metadata collection. This collection contains only one single document listing all the values (obtained with mongodb distinct function) for the major fields.

Here is the GraphQL query:

1query {
2 metadatum {
3 _id
4 countries
5 states
6 states_us
7 counties
8 iso3s
9 uids
10 first_date
11 last_date
12 }
13}

Now let's build an HTTP query with it. Don't forget to replace the ACCESS_TOKEN in the query with your own valid token.

1curl 'https://realm.mongodb.com/api/client/v2.0/app/covid-19-qppza/graphql' \
2 --header 'Authorization: Bearer ACCESS_TOKEN' \
3 --header 'Content-Type: application/json' \
4 --data-raw '{"query": "query { metadatum { _id countries states states_us counties iso3s uids first_date last_date } }" }'

This will answer a JSON document which will help you populate your filters for the other queries:

1{"data":
2 {"metadatum":
3 {
4 "_id":"metadata",
5 "countries": [ "Afghanistan", "Albania", "Algeria","..."],
6 "states":["Alabama","Alaska","Alberta","American Samoa","..."],
7 "states_us":["Alabama","Alaska","American Samoa","..."],
8 "counties":["Abbeville","Acadia","Accomack","..."],
9 "iso3s":["ABW","AFG","AGO","..."],
10 "uids":[4,8,12,16,...],
11 "first_date":"2020-01-22T00:00:00Z",
12 "last_date":"2020-09-23T00:00:00Z"
13 }
14 }
15}

#Query 2. The countries_summary Collection

Now let's refine our data query even further. We want to see how France is trending for the last week, so we will use a query filter:

1{country: "France", date_gte: "2020-09-16T00:00:00Z"}

Plus we will sort the dates in descending order with the most recent dates first. Remember with GraphQL, we can request as many or as few data fields as we want for the client. In this example, we'll only ask for the number of confirmed cases, deaths, and recoveries, along with the date. The final query with this filter and those specific fields is:

1query {
2 countries_summarys(query: {country: "France", date_gte: "2020-09-16T00:00:00Z"}, sortBy: DATE_DESC) {
3 confirmed
4 date
5 deaths
6 recovered
7 }
8}

Or with cURL:

1curl 'https://realm.mongodb.com/api/client/v2.0/app/covid-19-qppza/graphql' \
2 --header 'Authorization: Bearer ACCESS_TOKEN' \
3 --header 'Content-Type: application/json' \
4 --data-raw '{"query": "query { countries_summarys(query: {country: \"France\", date_gte: \"2020-09-16T00:00:00Z\"}, sortBy: DATE_DESC) { confirmed date deaths recovered } }" }'

Which gives me:

1{
2 "data": {
3 "countries_summarys": [
4 {
5 "confirmed": 507150,
6 "date": "2020-09-22T00:00:00Z",
7 "deaths": 31426,
8 "recovered": 94961
9 },
10 {
11 "confirmed": 496851,
12 "date": "2020-09-21T00:00:00Z",
13 "deaths": 31346,
14 "recovered": 94289
15 },
16 {
17 "confirmed": 467614,
18 "date": "2020-09-20T00:00:00Z",
19 "deaths": 31257,
20 "recovered": 93586
21 },
22 {
23 "confirmed": 467614,
24 "date": "2020-09-19T00:00:00Z",
25 "deaths": 31257,
26 "recovered": 93586
27 },
28 {
29 "confirmed": 467421,
30 "date": "2020-09-18T00:00:00Z",
31 "deaths": 31257,
32 "recovered": 92700
33 },
34 {
35 "confirmed": 454266,
36 "date": "2020-09-17T00:00:00Z",
37 "deaths": 31103,
38 "recovered": 91765
39 },
40 {
41 "confirmed": 443869,
42 "date": "2020-09-16T00:00:00Z",
43 "deaths": 31056,
44 "recovered": 91293
45 }
46 ]
47 }
48}

#Query 3. The global_and_us Collection

Finally, let's find the three counties in the USA with the greatest number of confirmed cases:

1query {
2 global_and_us(query: {country: "US", date: "2020-09-22T00:00:00Z"}, sortBy: CONFIRMED_DESC, limit: 3) {
3 confirmed
4 deaths
5 state
6 county
7 }
8}

Or with cURL:

1curl 'https://realm.mongodb.com/api/client/v2.0/app/covid-19-qppza/graphql' \
2 --header 'Authorization: Bearer ACCESS_TOKEN' \
3 --header 'Content-Type: application/json' \
4 --data-raw '{"query": "query { global_and_us(query: {country: \"US\", date: \"2020-09-22T00:00:00Z\"}, sortBy: CONFIRMED_DESC, limit: 3) { confirmed deaths state county } }" }'

Results:

1{
2 "data": {
3 "global_and_us": [
4 {
5 "confirmed": 262133,
6 "county": "Los Angeles",
7 "deaths": 6401,
8 "state": "California"
9 },
10 {
11 "confirmed": 167515,
12 "county": "Miami-Dade",
13 "deaths": 3085,
14 "state": "Florida"
15 },
16 {
17 "confirmed": 140314,
18 "county": "Maricopa",
19 "deaths": 3275,
20 "state": "Arizona"
21 }
22 ]
23 }
24}

#But How Did I Build This GraphQL API?

Simple and easy, I used the MongoDB Realm GraphQL API which just took me a few clicks.

If you want to build this very same service using this dataset, check out our blog which explains the dataset's content and how you can grab it. Then, have a look at Nic's blog post which explains how to set up a GraphQL API using MongoDB Realm.

You want to improve your knowledge even more around MongoDB and GraphQL? Then you must read the blog post GraphQL: The Easy Way to Do the Hard Stuff from Karen and Brian.

#Wrap-Up

MongoDB made setting up a GraphQL API really easy. And this GraphQL API made querying our Covid19 dataset to gain insight even easier. We update this data every hour, and we hope you will enjoy using this data to explore and learn.

Are you trying to help solve this pandemic in any way? Remember that if you are trying to build an application that helps to detect, understand, or stop the spread of the COVID-19 virus, we have a FREE MongoDB Atlas credit program that can help you scale and hopefully solve this global pandemic.

I truly hope you will be able to build something amazing with this GraphQL API. Even if it won't save the world from the COVID-19 pandemic, I hope it will be a great source of motivation and training for your next pet project.

Send me a tweet or ping me in our Community Forum with your project using this API. I will definitely check it out!

Rate this article

More from this series

COVID-19
  • Coronavirus Map and Live Data Tracker with MongoDB Charts
  • How to work with Johns Hopkins University COVID-19 Data in MongoDB Atlas
  • A Free REST API for Johns Hopkins University COVID-19 dataset
  • A Free GraphQL API for Johns Hopkins University COVID-19 Dataset
  • Aggregation Pipeline: Applying Benford's Law to COVID-19 Data

Related

Article: Introducing GraphQL Support in MongoDB Atlas
Article: GraphQL: The Easy Way to Do the Hard Stuff
Video: GraphQL: The Easy Way to Do the Hard Stuff
Video: Realm Creating Sophisticated GraphQL APIs in Minutes
MongoDB logo
© 2021 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2021 MongoDB, Inc.