DEV Community

TrackMyStories
TrackMyStories

Posted on

How to GeoJSON with Apollo GraphQL Server

Alt Text

This article explains in a few simple steps how to work with GeoJSON using an Apollo GraphQL server, The primary focus is to understand the fetching of numeric properties within an array.

coordinates : [55.708, -21.244]

For this example I have utilised NASA API's : The Earth Observatory Natural Event Tracker (EONET), which is a repository of metadata about natural events.

In addition you can find the example linked here on github here.

In order to work with GeoJSON using Apollo's graphQL server we have to make use of custom scalars, because the servers backend needs to know how to interact with a data structure which includes an array example as such "[55.708, -21.244]."

Step 1:

$ npm install graphql-type-json

The following dependency defines a custom scalar object. The GraphQLJSON object is an instance of the GraphQLScalarType which can be used to define the custom scalar JSON , this will allow our server to validate our coordinates e.g. "[55.708, -21.244]."

Step 2:

In the schema.js file define the custom scalar type and link it to the coordinates:

const {gql} = require('apollo-server');
const typeDefs = gql`
  scalar JSON  // custom scalar
type Event {
    id: ID!
    cursor: ID!
    title: String
    description: String
    link: String
    closed: String
    categories: [Categories]
    sources: [Sources]
    geometry: [Geometry]
  }
type Categories {
    id: ID!
    title: String
  }
type Sources {
    id: String
    url: String
  }
type Geometry {
    magnitudeValue: String
    magnitudeUnit: String
    date: String
    type: String
    coordinates: [JSON] // coordinates 
  }
type Query {
    events: [Event!]!
  }
`;
module.exports = typeDefs;
Enter fullscreen mode Exit fullscreen mode

Step 3:

In the index.js file import GraphQLJSON and add to the server constructor.

const {ApolloServer} = require('apollo-server');
const typeDefs = require('./src/schema');
const resolvers = require('./src/resolvers');
const EventsAPI = require('./src/datasources/events');
const GraphQLJSON = require('graphql-type-json');
const server = new ApolloServer({
  typeDefs,
  resolvers,
  JSON: GraphQLJSON,
  dataSources: () => ({
    eventsAPI: new EventsAPI(),
  }),
});
server.listen().then(({url}) => {
  console.log(`🚀 Server ready at ${url}`);
});
Enter fullscreen mode Exit fullscreen mode

This example uses apollo-datasource-rest and passes the api to the resolvers:

events.js creates and exports = EventsAPI;

const {RESTDataSource} = require('apollo-datasource-rest');
class EventsAPI extends RESTDataSource {
  constructor() {
    super();
    this.baseURL = 'https://eonet.sci.gsfc.nasa.gov/api/v3/';
  }
async queryAllEvents() {
    const response = await this.get('events');
    return response.events;
  }
async getAllEvents() {
    const response = await this.queryAllEvents();
    return Array.isArray(response)
      ? response.map(item => this.eventReducer(item))
      : [];
  }
eventReducer(item) {
    return {
      id: item.id,
      title: item.title,
      description: item.description,
      link: item.link,
      closed: item.closed,
      categories: item.categories.map(i => ({
        id: i.id,
        title: i.title,
      })),
      sources: item.sources.map(i => ({
        id: i.id,
        url: i.url,
      })),
      geometry: item.geometry.map(i => ({
        magnitudeValue: i.magnitudeValue,
        magnitudeUnit: i.magnitudeUnit,
        date: i.date,
        type: i.type,
        coordinates: i.coordinates,
      })),
    };
  }
}
module.exports = EventsAPI;
Enter fullscreen mode Exit fullscreen mode

and is passed to the resolvers like such:

resolvers.js

module.exports = {
  Query: {
    events: (_, __, {dataSources}) => dataSources.eventsAPI.getAllEvents(),
  },
};
Enter fullscreen mode Exit fullscreen mode

Step 3:

Run the following query in the graphQL playground:

# Write your query or mutation here

query Query {
 events {
      geometry {
        date
        type
        coordinates
      }
    }  
}
Enter fullscreen mode Exit fullscreen mode

Output:

Alt Text

And the output will be as such.

To conclude:

You can find the code for this example here on github.

To get a deeper understanding, please refer to the Apollo federation documentation on custom scalars here.

Discussion (0)