astorbDB Graphql API Access

Introduction

astorbDB is a modern relational database provided and maintained by Lowell Observatory. It is a significant modernization of the historical (but still maintained) astorb.dat file. For basic and moderate queries, see the tools available at https://asteroid.lowell.edu/ as they are generally easier to use and more appropriate for "one-off" and basic queries. For complex queries, or programatic and regular access, Lowell Observatory maintains a GraphQL API for accessing the astorbDB database.

GraphQL

Very basically, GraphQL is simply a way to query data from a database. GraphQL is a query language defining how data is requested and returned. In this way, it works similiarly to standard SQL queries, but over a RESTful interface. For general usage of GraphQL see the official docs.

The basic steps for using any GraphQL API are:

  1. Write a query
  2. Submit the query
  3. Recieve the results
GraphQL specifies how each of these steps are formatted and processed. Below are more details for the astorbDB GraphQL API.

Getting Started

Unlike traditional REST APIs, GraphQL APIs typically specify only one endpoint. The astorbDB GraphQL endpoint is:

https://astorbdb.lowell.edu/v1/graphql

Every request is structured as a POST request, with the the desired query being sent in the body of the request. For example, a basic cURL request might be structured as:

curl -g -X POST -H "Content-Type: application/json" -d '{"query": "GRAPHQL QUERY HERE"}' https://astorbdb.lowell.edu/v1/graphql

The same in Python would be like:

import requests

response = requests.post(
    "https://astorbdb.lowell.edu/v1/graphql",
    json={"query": "GRAPHQL QUERY HERE"}
)

print(response.json()

GraphQL API repsponses are JSON and can be parsed and traversed as such.

Exploring the Schema

Likely, the largest hurdle when using GraphQL APIs is learning how to structure the query. The structure, available fields, and relations within the GraphQL API are known as the schema. Probably the best way to understand the API schema and build queries is to use a graphical GraphQL explorer. An example of a great desktop client is Altair GraphQL Client . Alternatively there are web clients like Hasura. In both cases, you provide the GraphQL endpoint (https://astorbdb.lowell.edu/v1/graphql) and the client will present a user interface for exploring the schema and for building and testing a GraphQL query.

GraphiQL

These GraphQL explorer clients are often built from GraphiQL and are generally presented in the same fasion with three major parts:

  1. GraphQL Endpoint
  2. Explorer
  3. Query and Results Pane
In some cases, the tools will also offer a "Docs" pane with minimal documentation about relationships and field types.

Basic GraphiQL Structure

Endpoint

This is the URL of the GraphQL API. In the case of astorbDB the endpoint is https://astorbdb.lowell.edu/v1/graphql

Explorer

This is arguably the most helpful part of the GraphiQL tools. The Explorer is a list of resources that are available for querying. Selecting a resource will trigger the UI to start building a GraphQL query as well as expand the fields and relationships for that resource.

For example, selecting the albedo resource will display the available fields and conditions that can be set on the query:

Selecting Resource Fields

In the example, we have selected the albedo resource, limited the results to the first 10 and are asking for only the albedo, albedo_error_lower, and albedo_error_upper values to be returned for the 10 results. Remember that in GraphQL you only get what you ask for. In this case, we have only specified for the three fields to be returned, so those are the only fields that will be returned.

Query and Results

In this interface, it is simple a matter of now executing this query and the results are returned.

Execute the Query to View the Results

These interfaces are great for exploring the API, working out a complex query, and for one-off investigations. Queries can quickly become complex, so this interface is a good way to validate that queries are working. Fundamentally, these tools are simply making POST requests to the API. In the same way, programatic access can be accomplished via many languages.

Programatic Access

Many times it is convenient to query the astorbDB API programatically. There are many tools across many different languages for creating, accessing, and parsing GraphQL APIs. When querying data, all these tools fundamentally work the same; a query is POST-ed to the specified endpoint, and the results are returned as a JSON payload. In many cases the JSON payload is transformed into another format for langauge-specific convenience.

Below we will provide a few examples using Python with the requests package. In this manner, the hope is that the examples are simple enough that they can easily be extrapolated to any language of choice.

Query Template

There are always three steps when executing a GraphQL request:

  1. Create the query
  2. Execute the query
  3. Parse the results

With this in mind, there is a standard patter in Python we can use for executing API calls.

# import the required requests package
import requests

# define the query to run
document = "SOME QUERY"

# sometimes we may wan to pass variables along with the query
variables = "SOME VARIABLES"

# execute the query agains the astorbDB GraphQL API endpoint
response = requests.post(
    "https://astorbdb.lowell.edu/v1/graphql",
    json={"query": document, "variables": variables}
)

# get the response as JSON
data = resonse.json()

With this defined, querying data is effectively just a matter of building the correct query. As stated in above, any GraphiQL interface is a good place to start when building queries. They will help to correctly stucture and debug queries. Below we will provide a few examples of queries and the resulting response:

First Example

Querying minorplant primary designations and number is a very basic example to start with. Below we access the minorplanet resource, ask for asteroid number and thier associated primary desicnations, and limit the query to 10 results.

Query

query MyQuery {
  minorplanet(limit: 10) {
    ast_number
    designameByIdDesignationPrimary {
      str_designame
    }
  }
}

Result

{
  "data": {
    "minorplanet": [
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2016 WP65"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2014 UH286"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2017 TQ24"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2013 TC243"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2022 QC31"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2009 UE193"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2000 QC148"
        }
      },
      {
        "ast_number": 123400,
        "designameByIdDesignationPrimary": {
          "str_designame": "2000 WY80"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2006 VJ20"
        }
      },
      {
        "ast_number": null,
        "designameByIdDesignationPrimary": {
          "str_designame": "2015 KN326"
        }
      }
    ]
  }
}

Using Variables

In the above example, we have hard-coded the number of results. GraphQL allows for passing of variables. A simple usage of passing variables to a query could be in the number of results returned.

query MyQuery($limit: Int = 10) {
  minorplanet(limit: $limit) {
    ast_number
    designameByIdDesignationPrimary {
      str_designame
    }
  }
}

Here, limit is declared as a variable of type Int with a default value of 10. Since a default value is specified, we can run this query successfully without any variable payload. If the default value is omitted, then the variable becomes required. If, for exmaple, only 5 results are required, we could attach query variables to the payload:

{"limit": 5}

Full Example

Using the Query Template and the above exmaple, we can build a complete and functional python script.

# import the required requests package
import requests

# define the query to run
document = """query MyQuery($limit: Int = 10) {
                minorplanet(limit: $limit) {
                  ast_number
                  designameByIdDesignationPrimary {
                  str_designame
                }
              }
            }"""

# sometimes we may wan to pass variables along with the query
variables = "{"limit": 5}"

# execute the query agains the astorbDB GraphQL API endpoint
response = requests.post(
    "https://astorbdb.lowell.edu/v1/graphql",
    json={"query": document, "variables": variables}
)

# get the response as JSON
data = resonse.json()
More Exmaples