Intro to GraphQL

GraphQL may seem foreign at first if you are used to working with REST APIs. The following guides will help you get familiar with GraphQL concepts so you can start building immediately.

Overview and Benefits

A GraphQL API makes all data available at a single endpoint. It also lets the client specify the exact data format of the response.

In contrast, REST APIs tend to have a different endpoint for each resource object. Fetching associated data often requires multiple HTTP calls to multiple endpoints that then must be joined together to perform analysis.

In addition, GraphQL only returns the data that is explicitly requested. If your use case does not require all of the data attributes, GraphQL can speed up your requests by targeting just the data elements that are necessary.

Finally, GraphQL is a self-documenting service. Check out the side bar in any of the GraphiQL editors to see all relevant queries and fields.

Queries

GraphQL queries are the way to fetch data from the servers. The query structure closely resembles JSON. There are two key parts to a query: the parameters that define the place or places you are looking for and then the information that you want returned for those places. Note those fields may have sub-fields as well.

Here is an example of fetching data for a point of interest (or POI) through a query.

query {
  lookup(placekey:  "zzy-225@5vg-82m-fzz") {
    locationName
		address {
      streetAddress
      city
      region
      postalCode
    }
    topCategory
    detailedInfo {
      subcategory
      categoryTags
    }
  }
}

The place() query type with the provided Placekey is defining the POI we are looking to gather information on. Then the following fields lay out exactly what information we want on that POI and in what order.

Here is the response to the above query:

{
  "data": {
    "lookup": {
      "locationName": "Hey Neighbor Cafe",
      "address": {
        "streetAddress": "2 Burrows St",
        "city": "San Francisco",
        "region": "CA",
        "postalCode": "94134"
      },
      "topCategory": "Restaurants and Other Eating Places",
      "detailedInfo": {
        "subcategory": "Snack and Nonalcoholic Beverage Bars",
        "categoryTags": [
          "Coffee Shop"
        ]
      }
    }
  },
  "extensions": {
    "row_count": 0
  }
}

The query and the result has the same shape. You always get back what you ask for from the API.

See Query Types for more sample queries and use cases. And for more information on GraphQL queries, see the official guide.

Pagination

Search requests are limited to 20 results per request. For queries that contain more than 20 items, you will need to paginate over the items. You can paginate over 50 pages to return up to 1000 places per query. To do this, you can specify pageNumber as an argument.

Below, we are specifying that we want the first page of results, by setting pageNumber: 0 (we use 0-based indexing). If you do not specify pageNumber, the API will return the first page.

Include pageInfo in your query to return information on results, such as totalCount, page, pages, and resultsPerPage.

query {
  textSearch(text: "coffee shops denver", pageNumber: 0) {
    places {
      locationName
      address {
        streetAddress
        city
        region
      }
    }
    pageInfo {
      totalCount
      page
      pages
      resultsPerPage
    }
  }
}

If you'd like the next page, set pageNumber: 1. You can iterate like so over each page of results.

query {
  textSearch(text: "coffee shops denver", pageNumber: 1) {
    places {
      locationName
      address {
        streetAddress
        city
        region
      }
    }
    pageInfo {
      totalCount
      page
      pages
      resultsPerPage
    }
  }
}

Fragments

A fragment is a reusable unit consisting of multiple fields. You can consolidate many repetitive fields from different queries into a fragment to repeatedly use those sets of fields. You can easily update the fragment by adding new fields. You may use multiple fragments within a query as well.

The below example shows an allAddressFields fragment that could be created consisting of all address fields from Place response.

fragment allAddressFields on Place {
  address {
    streetAddress
    city
    region
    postalCode
    isoCountryCode
  }
}

For the above fragment to be valid, the Place type must have all the fields present in the allAddressFields fragment . The fragment has a subset of the fields from its associated type.

query {
  lookup(placekey: "zzy-225@5vg-82m-fzz") {
    ...allAddressFields
  }
}

The above request is the same as:

query {
  lookup(placekey: "zzy-225@5vg-82m-fzz") {
    address {
    streetAddress
    city
    region
    postalCode
    isoCountryCode
 	  }
  }
}

Variables

Variables may have dynamic values in most of the applications. Variables are passed to the query with the $ symbol.

To use variables, replace the static value in the query with the name of the variable. (e.g. $placekey). Declare the variable name ($placekey) as one of the variables accepted by the query. Then you can pass the values dynamically as part of each query. This is a great tool for iterating through a list of inputs (say a list of placekeys or a list of brands or a list of NAICS codes, etc.) because you can leave the query exactly the same and just change the variables that get passed on each call.

query($placekey: String!) {
  lookup(placekey: $placekey) {
    locationName
  }
}
{
 "placekey":  "zzy-225@5vg-82m-fzz"
}

Learning Resources

The official GraphQL documentation provides a great overview of the basics as well as advanced topics.

Visit Data Science Resources for additional information and plenty of notebooks and white papers on using SafeGraph data in a variety of ways.