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: "[email protected]"){
    placekey
    safegraph_core {
      location_name
      region
      postal_code
    }
  }
}

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": {
    "placekey": "[email protected]"
    "safegraph_core": {
        "location_name" : "McDonald's"
        "region" : "CA"
        "postal_code": "94102"
    }
  }
}

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.

Arguments

You may pass arguments as part of the query to increase specification. For the below search, we're using arguments to define the number of records (first 10) and the specific portion of the list (after 50).

query {
  search(first: 10 filter:{
         brand: "Starbucks"}) {
    places {
      pageInfo { hasNextPage, endCursor}
      edges {
        node {
          placekey
          safegraph_core {
            location_name 
            region
            postal_code
          }
        }
      }
    }
  }
}

Pagination

Search requests are limited to 500 results per request. For queries that contain more than 500 items, you will need to paginate over the items. To do this, you will need to ask for the cursor of the last item. You can make a request the the pageInfo object to get the endCursor and if there hasNextPage.

To pull in those fields, make a call to pageInfo and request the endCursor and hasNextPage fields.

query {
  search(filter:{
         brand: "Starbucks"}) {
    places {
      pageInfo { hasNextPage, endCursor}
      edges {
        node {
          placekey
          safegraph_core {
            location_name 
            region
            postal_code
          }
        }
      }
    }
  }
}

Now add in the number of fields you want to pull in per request with the first parameter. For this example, we will pull in the maximum amount at 500.

query {
  search(first:500 filter:{
         brand: "Starbucks"}) {
    places {
      pageInfo { hasNextPage, endCursor}
      edges {
        node {
          placekey
          safegraph_core {
            location_name 
            region
            postal_code
          }
        }
      }
    }
  }
}

Now, to request the next 500, you will pull in the endCursor to make another request.

{
  "data": {
    "search": {
      "places": {
        "pageInfo": {
          "hasNextPage": true,
          "endCursor": "UGxhY2U6MjIyLTIyMkA1czgtY2Q2LWh5dg=="
        },
        "edges": [...]
      }
    }
  }
}
query {
  search(first:500 after:"UGxhY2U6MjIyLTIyMkA1czgtY2Q2LWh5dg==" filter:{
         brand: "Starbucks"}) {
    places {
      pageInfo { hasNextPage, endCursor}
      edges {
        node {
          placekey
          safegraph_core {
            location_name 
            region
            postal_code
          }
        }
      }
    }
  }
}

Fragments

A fragment is a reusable unit consisting of multiple fields. You can consolidate many repetitive fields from different queries into a fragment. It lets you share those sets of fields in multiple queries with ease. You can make recurring calls for a long list of fields using fragments without repeatedly listing out every field. 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 the safegraph_core dataset. Using this fragment prevents you from having to list out each field each time you want this information. It also allows you to update the fragment to potentially include new fields and not need to go about any queries already referencing the fragment.

fragment allAddressFields on Place {
  safegraph_core {
    location_name
    street_address
    city
    region
    postal_code
    iso_country_code
  }
}

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: "[email protected]") {
    placekey
    ...allAddressFields
  }
}

The above request is the same as:

query {
  lookup(placekey: "[email protected]") {
    placekey
    safegraph_core {
      location_name
      street_address
      city
      region
      postal_code
      iso_country_code
    }
  }
}

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 {
  lookup($placekey: Placekey) {
    safegraph_core {
      adrress {
        postal_code
      }
    }
  }
}
{
 placekey: "[email protected]" 
}

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.