How does one return and accept a geolocation type in GraphQL? Something that has a
The naive approach is to create a location type with a latitude and longitude.
This can be returned as
field :location, Types::LocationType in any GraphQL
To accept a location in a mutation we create an input type with the same properties.
A query can ask for a location.
This needs to be wired to our MongoDB storage. I’m using mongoid-geospatial and saving locations as a Point. The latter can accept latitude and logitude but then stores these as
y. The location type specifies
property: :x and
property :y where appropriate, which is used when converting a
Point into a
LocationType, while the mutation converts input to a hash that is fed into
Custom GraphQL Scalar Type
The naive approach requires separate input and output types and the knowledge of a location internals (latitude, longitude). Lets elevate a location to a first class scalar type, similar to how dates and times are implemented and call this geo coordinates. I’m using geo_coord that can parse and format geo coordinates according to multiple existing conventions, such as pairs of latitude and longitude or a combination of degrees, minutes and seconds.
We need to implement
Point#to_s used above and convert a
Geo::Coord to a
Hash with latitude and longitude in our mutations to wire this up with mongoid-geospatial.
Point seems to implement support for latitude and longitude backwards. This is mongoid-geospatial#61.
This is implemented in 33-minutes-server@28f309.
The values passed back-and-forth are much more readable now and our API accepts standard notations (eg.
50.004444, 36.231389 or
50° 0′ 16″ N, 36° 13′ 53″ E) and returns a
location as a string (eg.
50° 0′ 16″ N, 36° 13′ 53″ E). This allows for seamless future improvements in the location formats, but burdens the client to parse a complex response.
The first attempt at easing this is to return a location in the simpler
We can do better and just return an array, as well as allow multiple kinds of location inputs.