GraphQL: directive for GraphQL+- custom resolver (e.g Geolocation)

I’m very impressed with the GraphQL API in Dgraph (extremely impressed with the @auth directive!).

I have, however, hit a bit of a roadblock in the POC phase for how this might work for the app that we’re building, in that I can’t seem to figure out how to implement geolocation fields, not really in any way a fault of Dgraph’s implementation as this isn’t handled in the official GraphQL spec (that I can find).

The issue for me is that our application is in the transport industry and as such, as you can imagine, it’s heavily reliant on the geolocation data.

My thoughts are that, just like the scalar DateTime appears to be a custom scalar type for Dgraph, with its operations interpreted and rewritten to run in the GraphQL± way, we could look to create Point and Polygon types (with geo index) which are in turn rewritten to be the appropriate geo:geojson string for the database.

We’d also need to implement the appropriate query (near, within, contains, intersects) and mutation syntaxes for each of these ‘types’.

I can picture that the structure of a Point would be something like:

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

and Polygon being something like:

#Creating PointList as I'm not able to find whether or not GQL allows for nested lists:
type PointList {
  Points: [Point!]
}

type Polygon {
  Coordinates: [PointList!]
}

#Probably implement MultiPolygon also as the Dgraph docs specify it as available
type MultiPolygon {
  Coordinates: [Polygon!]
}

Unless I’m mistaken, the above should match the GraphQL± specification for Geolocation in the docs and therefore should be ‘translatable’ to GraphQL± queries and mutations:
https://dgraph.io/docs/query-language/#geolocation

I’d be interested to hear opinions on the above or if I’m heading up the wrong path with this?

1 Like

Hi @machship-mm,

Handling geo data is a powerful feature that dgraph provides out of the box. But, currently it is only limited to the GraphQL± queries. I understand that it would be a very good feature to have in GraphQL too. Currently, it is not in our near-future roadmap, but we may add this capability later down the road. It would be great if you could propose it on GitHub as a feature request. That way, if many community users upvote the issue, we will try to pick it up early on.

Cheers!

1 Like

In addition;

As I mentioned on Slack. That would be easy to have in GraphQL after we give support to internal Graphql+- queries via the directive @custom. There is a roadmap for this. And I believe that the implementation would be easy as any @custom approach is today.

Actually it would virtually support all goodies from Graphql+-. Like multiple blocks and vars or other specific features that GraphQL specs won’t support in near future.

Thanks guys!

@MichelDiz, that’s definitely interesting… do we have a rough timeline/estimate on the completion of the @custom directive? Otherwise I was considering potentially having a go at adding the code for the Geolocation stuff I mentioned above (following effectively whatever was implemented in the code for DateTime).

Ah! I had forgot to mention this:

As a workaround for now, you can do it using the current implementation of @custom directive. It is not yet released, but is there in latest master branch. Currently, @custom allows you to call a remote HTTP REST/GraphQL api. So, if you were to expose a REST/GraphQL endpoint for the queries and mutations you wanted to perform for the geo data, and have that endpoint directly perform the graphql+- queries/mutations on a dgraph instance, then it would work for now.

I guess @michaelcompton can clarify the timeline about adding graphql+- in @custom directive.

Thanks @abhimanyusinghgaur; as I’m in the POC stage (and am working off the master branch anyway), I’m not in a huge rush but that certainly would be a way of doing it. I think I’d probably prefer to either wait for the remainder of the @custom directive functionality or, if that’s a long time off, just implement the Geo stuff myself as I noted above.

One question would be though, would that kind of contribution be welcome or would you guys prefer to only have the @custom directive for all future ‘extra stuff’ for the GraphQL API?

Yeah, In theory, as Dgraph has a REST API endpoint. You could send Graphql+- queries to that endpoint. But we have not tested it. Feels feasible. But I think native communication with Dgraph itself would be faster.

@machship-mm try that. Hit our HTTP API https://dgraph.io/docs/clients/#raw-http with todays HTTP custom implementation. And mount the schema as it is (but based in your need of course) in the custom directive docs. https://graphql.dgraph.io/custom/directive

1 Like

Thanks guys, I’ll give that a go.

Can I confirm that you think I’d be able to achieve the querying side of things (near, intersects, within, contains) with the @custom directive via the HTTP call?

Yes! it can be done. We haven’t tried it yet, but it should be feasible.

And, contributions from community are always welcome :slight_smile:

@michaelcompton can clarify more on whether @custom should have all the extra stuff.

1 Like

I believe it would be enough to use like

method: "POST",
body: "{ # GraphQL plus-minus here }"

As it has never been tested (and I have not worked on this code) I cannot say with 100% certainty. But it should be possible because any client that sends a payload via body works with Dgraph.

Excellent. I’ll give it a crack and come back to you about my success/failure if you would like?

Please! let us know. If it doesn’t work, I think there is an easy solution for this case (via HTTP).

Sorry guys, one final quick question… I would assume that as the GraphQL API will be the ‘one’ running the HTTP call to the GraphQL± API, I should direct the HTTP call to localhost?

For @custom, the body has to be JSON.
For graphql+- requests to /query, the body is sent as text/plain. So, you can’t directly write graphql+- in @custom body. You, will have to write a separate backend app to do that thing. The separate backend app will form the proper graphql+- query and send it to dgraph. The url of the separate backend app can be specified in @custom with whatever JSON payload you would want to send that endpoint.

Yes.

So let’s create a text place in the custom params. That would be handy.

@abhimanyusinghgaur In fact, it would be easy to get around that. Dgraph supports JSON format queries. He can just send something like:

method: "POST",
body: "{  "query": "{ q(func: eq(email, \"user@company1.io\")) {uid  name} }"}"
1 Like

I’ll give this a go!

The Geo features appear to be supported by the JSON API:
https://dgraph.io/docs/mutations/#geolocation-support

Yes, I too just discovered this:
The /query endpoint accepts two content types:

  1. application/json
  2. application/graphql± (sorry, this is what I meant by text/plain earlier)

For application/json, it accepts the following JSON object:

{
  "query": "some graphql+- query",
  "variables": map[string]string
}

But, I am not sure how to send variables in that query so that it could be directly plugged into @custom.

We will think about this.

1 Like

I think the only issue would be the query. Need to check if mutations need to be via HTTP API. I think it would run normally in GraphQL mutations.

Just want to jump in here and say that this support/level of discussion is incredible, guys.

6 Likes