How to get all of the records in COVID-19 Data Lake linelistrecords

Viewed 322

I'd like to use the https://api.c3.ai/covid/api/1/linelistrecord/fetch API but only get 2000 records back. I know that there are more than 2000 records -- how do I get them?

Here's my code in R:

library(tidyverse)
library(httr)
library(jsonlite)

resp <- POST(
  "https://api.c3.ai/covid/api/1/linelistrecord/fetch",
  body = list(
    spec = {}
  ) %>% toJSON(auto_unbox = TRUE),
  accept("application/json")
)

length(content(resp)$objs)

I get 2000 records.

2 Answers

The spec you are passing in has the following optional fields, among others:

  • limit // maximum number of objects to return
  • offset // offset to use for paged reads

The default value of limit is 2000.

The fetch result that is returned has a boolean field, along with the array of objects, called hasMore, which indicates whether there are more records in the underlying data store.

You can write a loop that ends once hasMore is false. Start with an offset of 0, and limit n (say , n=2000), and then iteratively increase offset by n.

library(tidyverse)
library(httr)
library(jsonlite)

limit <- 2000
offset <- 0
hasMore <- TRUE
all_objs <- c()

while(hasMore) {
  resp <- POST(
    "https://api.c3.ai/covid/api/1/linelistrecord/fetch",
    body = list(
      spec = list(
        limit = limit,
        offset = offset,
        filter = "contains(location, 'California')" # just as an example, to cut down on the dataset
      )
    ) %>% toJSON(auto_unbox = TRUE),
    accept("application/json")
  )
  hasMore <- content(resp)$hasMore
  offset <- offset + limit
  all_objs <- c(all_objs, content(resp)$objs)
}

length(all_objs)

You could also do something similar in Python too. Here is a code snippet for doing the same in Python

import requests
headers = {'Accept': 'application/json'}
import io
import pandas as pd

def read_data(url, payload, headers = headers):

    df_list = []
    has_more = True
    offset = 0
    payload['spec']['offset'] = offset
    while has_more:
        response = requests.post('https://api.c3.ai/covid/api/1/linelistrecord/fetch', json=payload, headers = headers)
        df = pd.DataFrame.from_dict(response.json()['objs'])
        has_more = response.json()['hasMore']
        payload['spec']['offset'] += df.shape[0]
        df_list.append(df)
    df = pd.concat(df_list)

    return df
url = 'https://api.c3.ai/covid/api/1/linelistrecord/fetch'
payload = {
    "spec":{
        "filter": "exists(hospitalAdmissionDate)",
        "include": "caseConfirmationDate, outcomeDate, hospitalAdmissionDate, age"
    }
}
df = read_data(url, payload)
Related