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;
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}`);
});
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;
and is passed to the resolvers like such:
resolvers.js
module.exports = {
Query: {
events: (_, __, {dataSources}) => dataSources.eventsAPI.getAllEvents(),
},
};
Step 3:
Run the following query in the graphQL playground:
# Write your query or mutation here
query Query {
events {
geometry {
date
type
coordinates
}
}
}
Output:
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.
Top comments (0)