# Implementing Geo features in GraphQL

**URL:** https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022
**Category:** Dev
**Tags:** rfc, graphql
**Created:** [June 4, 2020, 1:46pm UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022 "2020-06-04T13:46:39Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![pawan](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pawan/32/1946_2.png) [@pawan](https://discuss.dgraph.io/u/pawan)
#### Post date: [June 4, 2020, 1:46pm UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/1 "2020-06-04T13:46:39Z")

</div>

# Motivation

Supporting Geolocation features natively in GraphQL so that users of the GraphQL API can benefit from them.

# User Impact

Users can directly use these features without having to define their own custom types and using custom queries.

# Implementation

[https://dgraph.io/docs/query-language/#geolocation](https://dgraph.io/docs/query-language/#geolocation) shows that Dgraph supports storing Point, Polygon, MultiPolygon geo types. We need to be able to support `near`, `within`, `contains` and `intersects` query filter. We can have custom scalars for these within our predefined GraphQL schema like below.

## Custom scalars

Inside GraphQL±, a predicate which has `geo` type can store data for a `Point`, `Polygon` or `MultiPolygon` but since GraphQL is strongly typed, a field inside a type will be able to only store one type of data.

```auto
type Point {
  Latitude: Float!
  Longitude: Float!
}

type PointList {
  Points: [Point!]!
}

type Polygon {
  Coordinates: [PointList!]!
}

type MultiPolygon {
  Coordinates: [Polygon!]!
}

```

## An example of using custom scalars

Say, we have a hotel type with has a location and area, something like below.

```auto
type Hotel {
  id: ID!
  name: String!
  location: Point
  // TODO - See if MultiPolygon has different behaviour from Polygon.
  area: Polygon
}

```

In the Dgraph schema that is generated, we would automatically add an index to these fields like below.

```auto
Hotel.location: geo @index(geo) .
Hotel.area: geo @index(geo) .

```

## Mutations

For this `AddHotelInput` and `HotelPatch` would contain `location` and `area`.

```auto
input AddHotelInput {
  name: String!
  location: Point
  area: Polygon
}

input AuthorPatch {
  name: String!
  location: Point
  area: Polygon
}

```

## Queries

We would generate the Geo queries as part of the Hotel filter so that it can be combined with other filters.

```auto
input NearFilter {
    Distance: Float!
    Coordinate: Point!
}

input WithinFilter {
    # TODO - Verify if we also allow searching with a MultiPolygon, the docs are not very clear about this.
    polygon: Polygon!
}

input ContainsFilter {
    # The user should be giving one of these.
    # TODO - Verify if this can also accept MultiPolygon as an input.
    point: Point
    polygon: Polygon
}

input IntersectsFilter {
    # The user should be giving one of these.
    polygon: Polygon
    mulitPolygon: MultiPolygon
}

input PointGeoFilter {
    near: NearFilter
    within: WithinFilter
}

input PolygonGeoFilter {
    near: NearFilter
    within: WithinFilter
    contains: ContainsFilter
    intersects: IntersectsFilter
}

input HotelFilter {
    location: PointGeoFilter
    area: PolygonGeoFilter
    and: HotelFilter
    or: HotelFilter
    not: HotelFilter
}

```

### near

GraphQL± Definition - Matches all entities where the location given by `predicate` is within `distance` meters of geojson coordinate `[long, lat]` .

```auto
graphql+-

{
  tourist(func: near(loc, [-122.469829, 37.771935], 1000) ) {
    name
  }
}

graphql

queryHotel(filter: {
    location: { 
        near: {
            coordinate: {
                latitute: 37.771935, 
                longitude: -122.469829
            }, 
            distance: 1000
        }
    }
}) {
  name
}

```

Note, the near query can be used for returning Point as well as Polygon, MultiPolygon that are near a point. So if the user used `area` instead of `location`, it should return Polygon’s near the given point.

### within

GraphQL± Definition - Matches all entities where the location given by `predicate` lies within the polygon specified by the geojson coordinate array.

```auto
graphql+-

{
  tourist(func: within(loc, [[[....]]] )) {
    name
  }
}

graphql

queryHotel(filter: {
    location: { 
        within: {
            polygon: {
                coordinates: [[[....]]],
            }
        }
    }
}) {
  name
}

```

The within query would allow searching for all geo entities (point, polygon) within a polygon. So they would be generated for all types.  
// TODO(pawan) - Verify if we support within queries for searching in a multipolygon.

### contains

GraphQL± Definition - Matches all entities where the polygon describing the location given by `predicate` contains geojson coordinate `[long, lat]` or given geojson polygon.

`ContainsFilter` would only be generated for Polygon/MultiPolygon.

```auto
graphql+-

{
  tourist(func: contains(loc, [-122.50326097011566, 37.73353615592843] )) {
    name
  }
}

graphql

queryHotel(filter: {
    area: { 
        contains: {
            point: {
                coordinates: [],
            }
        }
    }
}) {
  name
}

```

### intersects

GraphQL± Definition - Matches all entities where the polygon describing the location given by `predicate` intersects the given geojson polygon.

`IntersectsFilter` would only be generated for Polygon/MultiPolygon.

```auto
graphql+-

{
  tourist(func: intersects(loc, [[[...]]] )) {
    name
  }
}

graphql

queryHotel(filter: {
    area: { 
        intersects: {
            polygon: {
                coordinates: [[[...]]],
            }
        }
    }
}) {
  name
}

```

# Needs further research

* * *

- Understanding of which functions are supported for MultiPolygon type. The docs don’t shed much light on this and we would have to dig deeper into the code to find this out.

# References

* * *

- To understand what Point, Polygon and MultiPolygon mean. [GeoJSON draft version 6 - GeoJSON](http://wiki.geojson.org/GeoJSON_draft_version_6)
- [https://dgraph.io/docs/query-language/#geolocation](https://dgraph.io/docs/query-language/#geolocation)

---

<div class="post-metadata">

### Author: ![gja](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/gja/32/2654_2.png) [@gja](https://discuss.dgraph.io/u/gja)
#### Post date: [June 4, 2020, 3:52pm UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/2 "2020-06-04T15:52:07Z")

</div>

I think we’d also want order by

---

<div class="post-metadata">

### Author: ![pawan](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pawan/32/1946_2.png) [@pawan](https://discuss.dgraph.io/u/pawan)
#### Post date: [June 5, 2020, 8:34am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/3 "2020-06-05T08:34:07Z")

</div>

We already have order by in GraphQL. Were you thinking of ordering by distance in the case of a near query?

---

<div class="post-metadata">

### Author: ![gja](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/gja/32/2654_2.png) [@gja](https://discuss.dgraph.io/u/gja)
#### Post date: [June 5, 2020, 8:47am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/4 "2020-06-05T08:47:05Z")

</div>

yes, ordering by distance from some point

---

<div class="post-metadata">

### Author: ![pawan](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pawan/32/1946_2.png) [@pawan](https://discuss.dgraph.io/u/pawan)
#### Post date: [June 5, 2020, 8:49am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/5 "2020-06-05T08:49:27Z")

</div>

We don’t have that in GraphQL± yet if I recall correctly, so we’ll skip that for the first pass and just focus on implementing the equivalent of what we already have. We can certainly implement the ordering after that.

---

<div class="post-metadata">

### Author: ![michaelcompton](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/michaelcompton/32/1774_2.png) [@michaelcompton](https://discuss.dgraph.io/u/michaelcompton)
#### Post date: [June 10, 2020, 1:02am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/6 "2020-06-10T01:02:02Z")

</div>

I think a user would end up using variables for these things. So my query in code would look like

```auto
query findHotel($at: Point, $distance: Float) {
queryHotel(filter: {
    location: { 
        near: {
            coordinate: $at, 
            distance: $distance
        }
    }
}) {
  name
}
}

```

Which seems pretty nice.

Definitely think we should only support what’s in Dgraph already. If any extra requirements come in. It’d probably have to be supported in Dgraph first, then bubbled into GraphQL.

One other thing I’d check is what sort of data structures do front end tooling that already does geo support - e.g. if there’s common JS libs in GraphQL for adding any of this to your app.

Also - **Let’s move this to public so community can see**

---

<div class="post-metadata">

### Author: ![machship-mm](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/machship-mm/32/3065_2.png) [@machship-mm](https://discuss.dgraph.io/u/machship-mm)
#### Post date: [June 12, 2020, 5:40am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/7 "2020-06-12T05:40:21Z")

</div>

Guys, this is absolutely fantastic.

FYI, you have a few copy/paste issues (naming is incorrect in a few places) but what you’ve written up here as a spec is exactly what I believe would suit our purposes. Incredible stuff!

The only thing I don’t see is pagination, but I don’t see that in the GQL docs either so that might not be a thing?

---

<div class="post-metadata">

### Author: ![michaelcompton](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/michaelcompton/32/1774_2.png) [@michaelcompton](https://discuss.dgraph.io/u/michaelcompton)
#### Post date: [June 13, 2020, 12:49pm UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/8 "2020-06-13T12:49:11Z")

</div>

Thanks for reading carefully enough to pick up the copy/paste errors! I think we’ll try to rewrite that top post collating any comments as we go, so we should 🤞 squash those.

As for pagination, we do support that in our GraphQL for the other queries, and it will ‘work’ here. However, I don’t think that sorting is supported in Dgraph’s geo queries at the moment (so you’d get pagination by node’s uid order). Some of them don’t have natural orderings anyway, e.g. within, but near probably could support and ordering.

We’ll look into it some more.

---

<div class="post-metadata">

### Author: ![mrjn](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/mrjn/32/775_2.png) [@mrjn](https://discuss.dgraph.io/u/mrjn)
#### Post date: [June 13, 2020, 2:53pm UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/9 "2020-06-13T14:53:53Z")

</div>

> [@michaelcompton](#):
>
> Also - **Let’s move this to public so community can see**

Love it! ❤ Awesome call, @michaelcompton .

---

<div class="post-metadata">

### Author: ![abhijit-kar](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/abhijit-kar/32/3726_2.png) [@abhijit-kar](https://discuss.dgraph.io/u/abhijit-kar)
#### Post date: [June 13, 2020, 3:41pm UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/10 "2020-06-13T15:41:16Z")

</div>

Hi Team,

I kept on googling about this for a long time. Finally posted on @mrjn post asking about new enthusiasts in June, in hopes of getting an answer.

And lo and behold, there’s a discussion going on about it!

I love it and can’t wait for this to be out.

Oh what a time to be alive!

---

<div class="post-metadata">

### Author: ![machship-mm](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/machship-mm/32/3065_2.png) [@machship-mm](https://discuss.dgraph.io/u/machship-mm)
#### Post date: [June 14, 2020, 1:24am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/11 "2020-06-14T01:24:32Z")

</div>

> [@michaelcompton](#):
>
> (so you’d get pagination by node’s uid order)

Any pagination is better than no pagination 🙂

---

<div class="post-metadata">

### Author: ![machship-mm](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/machship-mm/32/3065_2.png) [@machship-mm](https://discuss.dgraph.io/u/machship-mm)
#### Post date: [August 28, 2020, 5:41am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/12 "2020-08-28T05:41:48Z")

</div>

Hi all, has this been implemented?

---

<div class="post-metadata">

### Author: ![pawan](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pawan/32/1946_2.png) [@pawan](https://discuss.dgraph.io/u/pawan)
#### Post date: [September 1, 2020, 6:18am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/15 "2020-09-01T06:18:15Z")

</div>

Hey @machship-mm

This hasn’t been implemented yet but looks like there is a lot of interest on this RFC so we’ll prioritize working on this during Sept.

---

<div class="post-metadata">

### Author: ![iyinoluwaayoola](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/iyinoluwaayoola/32/4282_2.png) [@iyinoluwaayoola](https://discuss.dgraph.io/u/iyinoluwaayoola)
#### Post date: [September 3, 2020, 5:06am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/16 "2020-09-03T05:06:11Z")

</div>

Great stuff! Can’t wait 🙂

---

<div class="post-metadata">

### Author: ![pawan](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/pawan/32/1946_2.png) [@pawan](https://discuss.dgraph.io/u/pawan)
#### Post date: [September 3, 2020, 10:09am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/17 "2020-09-03T10:09:18Z")

</div>

@arijit is starting work on this and it should land in master by the end of the month!

---

<div class="post-metadata">

### Author: ![abhimanyusinghgaur](https://yyz1.discourse-cdn.com/flex007/user_avatar/discuss.dgraph.io/abhimanyusinghgaur/32/2980_2.png) [@abhimanyusinghgaur](https://discuss.dgraph.io/u/abhimanyusinghgaur)
#### Post date: [October 22, 2020, 4:40am UTC](https://discuss.dgraph.io/t/implementing-geo-features-in-graphql/7022/18 "2020-10-22T04:40:07Z")

</div>

It is now in master branch, and will be part of 20.11 release.  
PRs:

- [Point](https://github.com/dgraph-io/dgraph/pull/6481)
- [Polygon and MultiPolygon](https://github.com/dgraph-io/dgraph/pull/6618)
